Home > OS >  rename multiple files from different directories at once
rename multiple files from different directories at once

Time:01-17

I have thousands of files in different folders that I would like to rename with their directories and, but less importantly, edit a few details after.

As a structure example:

FOLDER A

---> folder 1

- 1.jpg
- 2.jpg

---> folder 2

- 1.jpg
- 2.jpg

FOLDER B

---> folder 1

- 1.jpg
- 2.jpg

...

The end name should be: FOLDER A_folder 1_1.jpg ...etc

and the less important edit: FOLDER A - 1_1.jpg ...etc

I don't know if it's relevant, but I have Ubuntu and from the terminal I've test tried this:

for file in Folders*/*/*/*.jpg; do
  mv "$file" "${file//\//_}";
done

It correctly renames the files with their paths but simultaneously extracts them and put them in the main folder, how do I avoid that?

CodePudding user response:

You need to add the path to the "target" file (the second parameter of the mv command) since you replaced all / with _ practically removing the path and making it part of the new name:

for file in FOLDER*/*/*; do
    mv "$file" "$(dirname "$file")/${file//\//_}";
done

TEST

Directories and files before running the loop:

$ find .
.
./FOLDER B
./FOLDER B/folder 2
./FOLDER B/folder 2/2.jpg
./FOLDER B/folder 2/1.jpg
./FOLDER B/folder 1
./FOLDER B/folder 1/2.jpg
./FOLDER B/folder 1/1.jpg
./FOLDER A
./FOLDER A/folder 2
./FOLDER A/folder 2/2.jpg
./FOLDER A/folder 2/1.jpg
./FOLDER A/folder 1
./FOLDER A/folder 1/2.jpg
./FOLDER A/folder 1/1.jpg
$

Renaming the files and the results:

$ for file in FOLDER*/*/*; do
>     mv "$file" "$(dirname "$file")/${file//\//_}";
> done
$ find .
.
./FOLDER B
./FOLDER B/folder 2
./FOLDER B/folder 2/FOLDER B_folder 2_1.jpg
./FOLDER B/folder 2/FOLDER B_folder 2_2.jpg
./FOLDER B/folder 1
./FOLDER B/folder 1/FOLDER B_folder 1_1.jpg
./FOLDER B/folder 1/FOLDER B_folder 1_2.jpg
./FOLDER A
./FOLDER A/folder 2
./FOLDER A/folder 2/FOLDER A_folder 2_1.jpg
./FOLDER A/folder 2/FOLDER A_folder 2_2.jpg
./FOLDER A/folder 1
./FOLDER A/folder 1/FOLDER A_folder 1_1.jpg
./FOLDER A/folder 1/FOLDER A_folder 1_2.jpg
$

As for your "less important edit," you can rename the files again, like this:

for file in FOLDER*/*/*; do
    mv "$file" "${file//_folder/ -}";
done

Note that you don't need to add the path here since the _folder to - substitution done to the file variable only affects the file name and not the path.

Final result:

$ find .
.
./FOLDER B
./FOLDER B/folder 2
./FOLDER B/folder 2/FOLDER B - 2_1.jpg
./FOLDER B/folder 2/FOLDER B - 2_2.jpg
./FOLDER B/folder 1
./FOLDER B/folder 1/FOLDER B - 1_1.jpg
./FOLDER B/folder 1/FOLDER B - 1_2.jpg
./FOLDER A
./FOLDER A/folder 2
./FOLDER A/folder 2/FOLDER A - 2_1.jpg
./FOLDER A/folder 2/FOLDER A - 2_2.jpg
./FOLDER A/folder 1
./FOLDER A/folder 1/FOLDER A - 1_1.jpg
./FOLDER A/folder 1/FOLDER A - 1_2.jpg

CodePudding user response:

This should do the trick:

SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
for f1 in `ls`; 
    do for f2 in `ls "$f1"`; 
        do for f3 in `ls $f1/$f2`; 
            do mv "$f1/$f2/$f3" "$f1/$f2/$f1_$f2_$f3"; 
        done; 
    done; 
done
IFS=$SAVEIFS
  • Related