[英]How to move and rename files based on parent folder in Linux?
I have a folder named photos
with the following structure: 我有一个名为
photos
的文件夹,结构如下:
00001/photo.jpg
00002/photo.jpg
00003/photo.jpg
I want to: 我想要:
photo.jpg
) to parent folder. photo.jpg
)中的文件重命名为父文件夹。 So the photos
folder would be something like this: 所以
photos
文件夹将是这样的:
00001.jpg
00002.jpg
00003.jpg
How can I do this in Terminal in Linux? 我怎么能在Linux的终端中做到这一点?
Note. 注意。 There are 100000+ such folders in
photos
. photos
有100000多个这样的文件夹。
Post edited since I've read in a comment that you have 100000+ such directories. 自从我在评论中读到你有100000多个这样的目录以来编辑后。
Do not use any method that involves bash globbing, it would be terribly slow and inefficient. 不要使用bash的涉及任何通配的方法,这将是非常缓慢和低效。 Instead, use this
find
command, from within the photos
directory: 而是在
photos
目录中使用此find
命令:
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. 我使用
-n
选项mv
这样我们就不会覆盖现有文件。 Use it if your version of mv
supports it. 如果您的
mv
版本支持它,请使用它。 You can also use the -v
option so that mv
is verbose and you see what's happening: 你也可以使用
-v
选项,这样mv
就是冗长的,你会看到发生了什么:
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 -regex '\\./[0-9]+'
:查找当前目录中名称中只有数字的所有内容 -type d
: and it must be a directory -type d
:它必须是一个目录 -exec mv -n -- {}/photo.jpg {}.jpg \\;
: move the photo.jpg
file in this directory into the parent directory, with name: dirname.jpg
photo.jpg
文件移动到父目录中,名称为: dirname.jpg
-empty
: if the directory is now empty... -empty
:如果目录现在为空... -delete
: ...delete it. -delete
:...删除它。 After that, you might want to see which directories have not been deleted (because eg, it contained more files than just the photo.jpg
file): 之后,您可能想要查看哪些目录尚未删除(例如,它包含的文件多于
photo.jpg
文件):
find -regex '\./[0-9]+' -type d
Enjoy! 请享用!
cd $toTheRootFolderWhichYouHaveALLtheFolders #00001, 00002
mv 00001/photo.jpg 00001.jpg
Or you can use this bash script in the "photos" directory: 或者您可以在“照片”目录中使用此bash脚本:
for entry in ./*;
do
mv "$entry"/photo.jpg "$entry".jpg ;
rm -rf "$entry";
done
Use a for loop, and printf -v
to zero pad the counter. 使用for循环,
printf -v
将计数器printf -v
零。 Example: 例:
for ((i=1;i<4;i++))
do
printf -v num "%05d" "$i";
mv "$num"/photo.jpg "$num".jpg
done
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.
如果任何子文件夹中有多个文件,并且您希望将其重命名为父目录名,则它将被覆盖。
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
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
. 我使用的一种简单方法是从
ls */*.jpg
(或者只是ls */*
)获取输出并处理输出以形成移动命令,如mv 00001/photo.jpg ./00001.jpg
,然后,您可以使用rmdir 00001
以类似方法轻松清理空文件夹。
To do it this using awk
at the bash terminal type: 为此,使用bash终端类型的
awk
:
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
您可以在运行它们之前轻松预览命令,而不必使用
| bash
| 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). 行结束时的
| bash
(查看生成的命令是什么,并在将它们传入bash以执行它们之前修复语法错误)。
Unfortunately, the output of ls */
includes empty lines that will mess with your rmdir
, but won't stop it from having the required effect. 不幸的是,
ls */
的输出包括会弄乱你的rmdir
空行,但不会阻止它具有所需的效果。
I find that this approach is quite powerful/flexible and easier than scripting a loop. 我发现这种方法非常强大/灵活,比编写循环更容易。 Use the method that makes sense to you.
使用对您有意义的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.