Reputation: 155
I have a folder named photos
with the following structure:
00001/photo.jpg
00002/photo.jpg
00003/photo.jpg
I want to:
photo.jpg
) to parent folder.So the photos
folder would be something like this:
00001.jpg
00002.jpg
00003.jpg
How can I do this in Terminal in Linux?
Note. There are 100000+ such folders in photos
.
Upvotes: 5
Views: 5297
Reputation: 1200
A simple way that I've used takes the output from something like ls */*.jpg
(or just ls */*
) and process the output to form a move command like mv 00001/photo.jpg ./00001.jpg
, and you can then easily clean-up the empty folders with a similar approach using rmdir 00001
.
To do it this using awk
at the bash terminal type:
ls */* | awk -F'/' '{print "mv " $0 " ./" $1 "_" $2 }' | bash
ls */ | awk -F'/' '{print "rmdir " $1 }' | bash
You can easily preview your commands before running them by leaving off the | bash
at the end of the line (to see what the generated commands are and fix syntax errors before you pipe them into bash to have them executed).
Unfortunately, the output of ls */
includes empty lines that will mess with your rmdir
, but won't stop it from having the required effect.
I find that this approach is quite powerful/flexible and easier than scripting a loop. Use the method that makes sense to you.
Upvotes: 1
Reputation: 180887
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
Upvotes: 0
Reputation: 1872
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
Upvotes: 2
Reputation: 46813
Post edited since I've read in a comment that you have 100000+ such directories.
Do not use any method that involves bash globbing, it would be terribly slow and inefficient. Instead, use this find
command, from within the photos
directory:
find -regex '\./[0-9]+' -type d -exec mv -n -- {}/photo.jpg {}.jpg \; -empty -delete
I've use the -n
option to mv
so that we don't overwrite existing files. Use it if your version of mv
supports it. You can also use the -v
option so that mv
is verbose and you see what's happening:
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 current directory that has only digits in its name-type d
: and it must be a directory-exec mv -n -- {}/photo.jpg {}.jpg \;
: move the photo.jpg
file in this directory into the parent directory, with name: dirname.jpg
-empty
: if the directory is now empty...-delete
: ...delete it.After that, you might want to see which directories have not been deleted (because e.g., it contained more files than just the photo.jpg
file):
find -regex '\./[0-9]+' -type d
Enjoy!
Upvotes: 5
Reputation: 77085
You can do something like:
find . -type f | while read -r file; do mv "$file" "${file%/*}"".jpg" ; done
Once you have all the files renamed and moved up to the parent folder, you can run the following command to delete all empty folders.
find . -type d -empty -exec rm -rf {} +
Please remember that the above solution is only for the structure you have presented. If you have multiple files in any of the sub-folder and you want it to rename it to parent directory name it will get overwritten.
Upvotes: 1
Reputation: 33317
Use a for loop, and printf -v
to zero pad the counter. Example:
for ((i=1;i<4;i++))
do
printf -v num "%05d" "$i";
mv "$num"/photo.jpg "$num".jpg
done
Upvotes: 0