How to move and rename files based on parent folder in Linux?

I have a folder called photos with the following structure:

 00001/photo.jpg 00002/photo.jpg 00003/photo.jpg 

I want to:

  • Rename the file to a folder (called photo.jpg ) in the parent folder.
  • Move the folder up.
  • Delete parent folder.

So, the photos folder will be something like this:

 00001.jpg 00002.jpg 00003.jpg 

How to do this in a terminal on Linux?

Note. There are 100,000+ such folders in photos .

+4
source share
6 answers

The post has been edited since I read in a comment that you have 100,000+ such directories.

Do not use any method that includes bash globbing, it will be terribly slow and inefficient. Instead, use this find from the photos directory:

 find -regex '\./[0-9]+' -type d -exec mv -n -- {}/photo.jpg {}.jpg \; -empty -delete 

I use the -n option for mv so that we do not overwrite existing files. Use it if your version of mv supports it. You can also use the -v option so that mv verbose and you see what happens:

 find -regex '\./[0-9]+' -type d -exec mv -nv -- {}/photo.jpg {}.jpg \; -empty -delete 

Read the previous command as:

  • -regex '\./[0-9]+' : find everything in the current directory that has only digits in the name
  • -type d : and it should be a directory
  • -exec mv -n -- {}/photo.jpg {}.jpg \; : move the photo.jpg file in this directory to the parent directory with the name: dirname.jpg
  • -empty : if the directory is empty ...
  • -delete : ... delete it.

After that, you may want to find out which directories have not been deleted (because, for example, it had more files than just the photo.jpg file):

 find -regex '\./[0-9]+' -type d 

Enjoy it!

+5
source
 cd $toTheRootFolderWhichYouHaveALLtheFolders #00001, 00002 mv 00001/photo.jpg 00001.jpg 

Or you can use this bash script in the "photos" directory:

 for entry in ./*; do mv "$entry"/photo.jpg "$entry".jpg ; rm -rf "$entry"; done 
+2
source

Use a for loop, and printf -v zero, skipping the counter. Example:

 for ((i=1;i<4;i++)) do printf -v num "%05d" "$i"; mv "$num"/photo.jpg "$num".jpg done 
0
source

You can do something like:

 find . -type f | while read -r file; do mv "$file" "${file%/*}"".jpg" ; done 

Once you rename all the files and navigate to the parent folder, you can run the following command to delete all empty folders.

 find . -type d -empty -exec rm -rf {} + 

Remember that the above solution is only for the structure you presented. If you have several files in any of the subfolders, and you want to rename them to the parent directory, they will be overwritten.

0
source

As far as I understand, this should do what you want.

 # Setup test data according to your structure $ mkdir 00001 00002 00003 $ touch 00001/photo.jpg 00002/photo.jpg 00003/photo.jpg # Rename, these are the commands you'll want to run to rename $ ls ?????/photo.jpg | xargs -I {} sh -c 'mv {} $(echo {} | sed "s,/photo,,")' $ rmdir ????? # Verify that the renames went ok $ ls 00001.jpg 00002.jpg 00003.jpg 
0
source

The simple method that I used outputs the output from something like ls */*.jpg (or just ls */* ) and processes the output to form a move command, for example mv 00001/photo.jpg ./00001.jpg , and you can easily clear empty folders with a similar approach using rmdir 00001 .

To do this, use awk in the bash terminal:

 ls */* | awk -F'/' '{print "mv " $0 " ./" $1 "_" $2 }' | bash ls */ | awk -F'/' '{print "rmdir " $1 }' | bash 

You can easily review your commands before running them, leaving | bash | bash at the end of the line (to find out what the generated commands are and fix syntax errors before sending them to bash to execute them).

Unfortunately, the output of ls */ includes empty lines that will work with your rmdir , but will not stop it from the desired effect.

I find this approach quite powerful / flexible and simpler than the loop script. Use a method that makes sense to you.

0
source

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


All Articles