Shell script to copy and add a folder name to files from multiple subdirectories

I have several folders with different file names for sharing files with a folder structure like this:

/parent/folder001/img001.jpg /parent/folder001/img002.jpg /parent/folder002/img001.jpg /parent/folder002/img002.jpg /parent/folder003/img001.jpg /parent/folder003/img002.jpg ... 

and would like to copy / rename these files to a new folder, for example:

 /newfolder/folder001_img001.jpg /newfolder/folder001_img002.jpg /newfolder/folder002_img001.jpg /newfolder/folder002_img002.jpg /newfolder/folder003_img001.jpg /newfolder/folder003_img002.jpg ... 

(It is probably better if the new folder is not a subfolder of the parent, as this can lead to really strange recursion.)

None of the image folders have subfolders.

Ideally, I would like to be able to reuse the new script folder for updating, as I may need to add more folders containing images later along the line.

How can I execute this with a shell script?

+6
source share
3 answers

This is a bit tedious, but will do:

 #!/bin/bash parent=/parent newfolder=/newfolder mkdir "$newfolder" for folder in "$parent"/*; do if [[ -d "$folder" ]]; then foldername="${folder##*/}" for file in "$parent"/"$foldername"/*; do filename="${file##*/}" newfilename="$foldername"_"$filename" cp "$file" "$newfolder"/"$newfilename" done fi done 

Place the parent path to the parent variable and the new directory to the newfolder variable.

+3
source

I would use something like this:

 find -type f -exec sh -c 'f={}; fnew=$(rev <<< "$f" | sed 's~/~_~' | rev); echo "mv $f $fnew"' \; 

It searches for files in the current directory structure and performs the following actions:

  • get file name
  • replace last / by _ .
  • write echo "cp $old_file $new_file"

Once you run this and see that it is printing the correct command, delete echo so that it effectively executes the mv command.

I know that fnew=$(rev <<< "$f" | sed 's~/~_~' | rev) is a bit ugly trick, but I couldn't find a better way to replace the last / with _ . Maybe sed -r 's~/([^/]*)$~_\1~' can also be approved, but I always like to use rev :)


Since your find does not work very well with the -sh c expression, use a while for it:

 while read -r file do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev) echo "mv $file $new_file"; done < <(find . -type f) done < <(find . -type f) 

As single line:

 while read -r file; do new_file=$(rev <<< "$file" | sed 's~/~_~' | rev); echo "mv $file $new_file"; done < <(find . -type f) 
+2
source

for rescue, update Jahid script:

 function updateFolder { mkdir "$2" for folder in "$1"/*; do if [[ -d $folder ]]; then foldername="${folder##*/}" for file in "$1"/"$foldername"/*; do filename="${file##*/}" newfilename="$foldername"_"$filename" cp "$file" "$2"/"$newfilename" done fi done } 

used by:

 $ updateFolder /parent /newfolder 
+2
source

Source: https://habr.com/ru/post/986143/


All Articles