简体   繁体   English

如何在Linux中基于父文件夹移动和重命名文件?

[英]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: 我想要:

  1. Rename the file within the folder (which called photo.jpg ) to parent folder. 将文件夹(名为photo.jpg )中的文件重命名为父文件夹。
  2. Move it a folder up. 将文件夹向上移动。
  3. Remove the parent folder. 删除父文件夹。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM