5

我有一个名为photos以下结构的文件夹:

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

我想要:

  1. 将文件夹(称为photo.jpg)中的文件重命名为父文件夹。
  2. 向上移动一个文件夹。
  3. 删除父文件夹。

所以photos文件夹会是这样的:

00001.jpg
00002.jpg
00003.jpg

如何在 Linux 的终端中执行此操作?

笔记。中有 100000+ 个这样的文件夹photos

4

6 回答 6

5

帖子已编辑,因为我在评论中读到您有 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!

于 2013-06-30T07:58:46.677 回答
2
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
于 2013-06-30T06:18:53.060 回答
1

您可以执行以下操作:

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

将所有文件重命名并移至父文件夹后,您可以运行以下命令删除所有空文件夹。

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

请记住,上述解决方案仅适用于您提供的结构。如果您在任何子文件夹中有多个文件,并且您希望将其重命名为父目录名称,它将被覆盖。

于 2013-06-30T06:30:28.447 回答
1

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.

于 2017-06-15T06:22:05.107 回答
0

使用 for 循环,并将printf -v计数器归零。例子:

for ((i=1;i<4;i++))
do 
    printf -v num "%05d" "$i"; 
    mv "$num"/photo.jpg "$num".jpg
done
于 2013-06-30T06:30:13.843 回答
0

据我了解,这应该做你想要的。

# 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
于 2013-06-30T06:36:49.710 回答