0

I've folder and file structure like


Folder/1/fileNameOne.ext
Folder/2/fileNameTwo.ext
Folder/3/fileNameThree.ext
...

How can I rename the files such that the output becomes


Folder/1_fileNameOne.ext
Folder/2_fileNameTwo.ext
Folder/3_fileNameThree.ext
...

How can this be achieved in linux shell?

TheKojuEffect
  • 20,103
  • 19
  • 89
  • 125

4 Answers4

2

How many different ways do you want to do it?

If the names contain no spaces or newlines or other problematic characters, and the intermediate directories are always single digits, and if you have the list of the files to be renamed in a file file.list with one name per line, then one of many possible ways to do the renaming is:

sed 's%\(.*\)/\([0-9]\)/\(.*\)%mv \1/\2/\3 \1/\2_\3%' file.list | sh -x

You'd avoid running the command through the shell until you're sure it will do what you want; just look at the generated script until its right.

There is also a command called rename — unfortunately, there are several implementations, not all equally powerful. If you've got the one based on Perl (using a Perl regex to map the old name to the new name) you'd be able to use:

rename 's%/(\d)/%/${1}_%' $(< file.list)
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I was just about to ask you out of curiosity if any of the `rename`s could do this (I never use them myself), since I was sure you would know. Your edit was faster :-) – Adrian Frühwirth Apr 11 '13 at 15:25
  • +1. Can't help learing more and more every day. `rename` is a command I did not know and for these cases is very powerful. – fedorqui Apr 11 '13 at 15:32
  • 1
    I use the version I cribbed from the 1st Edition of the Camel Book (the original Programming Perl, for Perl 4), though I've mildly updated it since then. See [How to rename with prefix/suffix](http://stackoverflow.com/questions/208181/how-to-rename-with-prefix-suffix/208389#208389) for the source. – Jonathan Leffler Apr 11 '13 at 15:33
  • @JonathanLeffler Sorry, but I'm having hard time implementing your idea. Suppose I'm at `MainFolder` and I don't have any `file.list`, how can I rename? I'm using Ubuntu and found out `rename` uses `Perl` expressions – TheKojuEffect Apr 11 '13 at 15:37
  • `find Folder -type f | sed ...`? Apply other criteria on the `find` as you need. Or use `find Folder -type f -exec rename 's%...%' {} +`. Or ... there are other options too. With `rename`, the `find -exec` is probably neatest. – Jonathan Leffler Apr 11 '13 at 15:38
2

Use a loop as follows:

while IFS= read -d $'\0' -r line
do
    mv "$line" "${line%/*}_${line##*/}"
done < <(find Folder -type f -print0)

This method handle spaces, newlines and other special characters in the file names and the intermediate directories don't necessarily have to be single digits.

dogbane
  • 266,786
  • 75
  • 396
  • 414
1

This may work if the name is always the same, ie "file":

for i in {1..3};
do
    mv $i/file ${i}_file
done

If you have more dirs on a number range, change {1..3} for {x..y}.

I use ${i}_file instead of $i_file because it would consider $i_file a variable of name i_file, while we just want i to be the variable and file and text attached to it.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
0

This solution from AskUbuntu worked for me.

Here is a bash script that does that:

Note: This script does not work if any of the file names contain spaces.

#! /bin/bash

# Only go through the directories in the current directory.
for dir in $(find ./ -type d)
do
    # Remove the first two characters. 
    # Initially, $dir = "./directory_name".
    # After this step, $dir = "directory_name".
    dir="${dir:2}"

    # Skip if $dir is empty. Only happens when $dir = "./" initially.
    if [ ! $dir ]
    then
        continue
    fi

    # Go through all the files in the directory.
    for file in $(ls -d $dir/*)
    do
        # Replace / with _
        # For example, if $file = "dir/filename", then $new_file = "dir_filename"
        # where $dir = dir
        new_file="${file/\//_}"

        # Move the file.
        mv $file $new_file
    done

    # Remove the directory.
    rm -rf $dir
done
  • Copy-paste the script in a file.
  • Make it executable using
chmod +x file_name
  • Move the script to the destination directory. In your case this should be inside Folder/.
  • Run the script using ./file_name.
Community
  • 1
  • 1
TheKojuEffect
  • 20,103
  • 19
  • 89
  • 125