【问题标题】:How to move and rename files based on parent folder in Linux?如何在 Linux 中基于父文件夹移动和重命名文件?
【发布时间】:2013-06-27 14:03:05
【问题描述】:

我有一个名为 photos 的文件夹,其结构如下:

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

我想:

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

所以photos 文件夹应该是这样的:

00001.jpg
00002.jpg
00003.jpg

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

注意。photos 中有 100000+ 个这样的文件夹。

【问题讨论】:

    标签: linux bash file command-line directory


    【解决方案1】:

    帖子已编辑,因为我在评论中读到您有 100000 多个此类目录。

    不要使用任何涉及 bash globbing 的方法,这会非常缓慢且效率低下。相反,请在 photos 目录中使用此 find 命令:

    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]+':在当前目录中查找名称中只有数字的所有内容
    • -type d: 必须是目录
    • -exec mv -n -- {}/photo.jpg {}.jpg \;:将该目录下的photo.jpg文件移动到父目录下,名称为:dirname.jpg
    • -empty: 如果目录现在是空的...
    • -delete: ...删除它。

    之后,您可能想查看哪些目录没有被删除(例如,它包含的文件不仅仅是photo.jpg 文件):

    find -regex '\./[0-9]+' -type d
    

    享受吧!

    【讨论】:

      【解决方案2】:
      cd $toTheRootFolderWhichYouHaveALLtheFolders #00001, 00002
      mv 00001/photo.jpg 00001.jpg
      

      或者您可以在“照片”目录中使用这个 bash 脚本:

      for entry in ./*; 
       do  
          mv "$entry"/photo.jpg "$entry".jpg ;
          rm -rf "$entry";
       done
      

      【讨论】:

      • 谢谢,但我有 100,000 多个这样的文件夹。一个一个执行?
      • 创建一个wtv.sh 文件,使用您喜欢的文本编辑器进行编辑,然后粘贴带有#!/bin/bash 作为标题的代码。然后设置previllages执行脚本chmod +x wtv.sh就可以了。
      • 或在“根文件夹”中你有另一个文件夹类型sh并粘贴代码。
      【解决方案3】:

      你可以这样做:

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

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

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

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

      【讨论】:

        【解决方案4】:

        我使用的一种简单方法从ls */*.jpg(或只是ls */*)获取输出并处理输出以形成mv 00001/photo.jpg ./00001.jpg 之类的移动命令,然后您可以轻松清理使用rmdir 00001 以类似方法清空文件夹。

        要在 bash 终端输入 awk 执行此操作:

        ls */* | awk -F'/' '{print "mv " $0 " ./" $1 "_" $2 }' | bash
        ls */ | awk -F'/' '{print "rmdir " $1 }' | bash
        

        您可以在运行命令之前轻松预览命令,方法是在行尾省略| bash(查看生成的命令是什么,并在将它们传送到 bash 以执行它们之前修复语法错误)。

        不幸的是,ls */ 的输出包含空行,这会与您的 rmdir 混淆,但不会阻止它产生所需的效果。

        我发现这种方法比编写循环脚本更强大/灵活且更容易。使用对您有意义的方法。

        【讨论】:

          【解决方案5】:

          使用 for 循环,printf -v 将计数器补零。示例:

          for ((i=1;i<4;i++))
          do 
              printf -v num "%05d" "$i"; 
              mv "$num"/photo.jpg "$num".jpg
          done
          

          【讨论】:

            【解决方案6】:

            据我了解,这应该可以满足您的要求。

            # 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
            

            【讨论】:

            • @mrz mkdir/touch的事情是根据他的问题设置文件来演示#Rename部分的重命名。编辑以使其更加清晰。我只是发现如果没有可以先使用的测试用例,重命名 100k 文件有点吓人。
            • 他不需要设置他的“规范”,因为他已经有了他的规范,答案应该一直针对 OP 的规范......不过重命名很好
            猜你喜欢
            • 2020-10-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-03-01
            • 2014-12-27
            • 2016-03-29
            • 2021-04-20
            相关资源
            最近更新 更多