我有一个名为photos
以下结构的文件夹:
00001/photo.jpg
00002/photo.jpg
00003/photo.jpg
我想要:
- 将文件夹(称为
photo.jpg
)中的文件重命名为父文件夹。 - 向上移动一个文件夹。
- 删除父文件夹。
所以photos
文件夹会是这样的:
00001.jpg
00002.jpg
00003.jpg
如何在 Linux 的终端中执行此操作?
笔记。中有 100000+ 个这样的文件夹photos
。
我有一个名为photos
以下结构的文件夹:
00001/photo.jpg
00002/photo.jpg
00003/photo.jpg
我想要:
photo.jpg
)中的文件重命名为父文件夹。所以photos
文件夹会是这样的:
00001.jpg
00002.jpg
00003.jpg
如何在 Linux 的终端中执行此操作?
笔记。中有 100000+ 个这样的文件夹photos
。
帖子已编辑,因为我在评论中读到您有 100000 多个此类目录。
不要使用任何涉及 bash globbing 的方法,这将非常缓慢且效率低下。相反,find
请在photos
目录中使用此命令:
find -regex '\./[0-9]+' -type d -exec mv -n -- {}/photo.jpg {}.jpg \; -empty -delete
我已经使用了这个-n
选项,mv
这样我们就不会覆盖现有文件。如果您的版本mv
支持它,请使用它。您还可以使用该-v
选项,以便mv
详细说明并查看发生了什么:
find -regex '\./[0-9]+' -type d -exec mv -nv -- {}/photo.jpg {}.jpg \; -empty -delete
将前面的命令读为:
-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!
cd $toTheRootFolderWhichYouHaveALLtheFolders #00001, 00002
mv 00001/photo.jpg 00001.jpg
或者你可以在“photos”目录中使用这个 bash 脚本:
for entry in ./*;
do
mv "$entry"/photo.jpg "$entry".jpg ;
rm -rf "$entry";
done
您可以执行以下操作:
find . -type f | while read -r file; do mv "$file" "${file%/*}"".jpg" ; done
将所有文件重命名并移至父文件夹后,您可以运行以下命令删除所有空文件夹。
find . -type d -empty -exec rm -rf {} +
请记住,上述解决方案仅适用于您提供的结构。如果您在任何子文件夹中有多个文件,并且您希望将其重命名为父目录名称,它将被覆盖。
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.
使用 for 循环,并将printf -v
计数器归零。例子:
for ((i=1;i<4;i++))
do
printf -v num "%05d" "$i";
mv "$num"/photo.jpg "$num".jpg
done
据我了解,这应该做你想要的。
# 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