【问题标题】:Remove a list of words from filename从文件名中删除单词列表
【发布时间】:2013-10-06 09:25:29
【问题描述】:

我正在尝试从特定目录的所有文件中删除特定单词的列表,并将它们替换为任何内容。

所以:

这个很棒的内容 720p BLAH FOO BANG OOO - 30.9.2013.mp4

变成:

这个很棒的内容 - 30.9.2013.mp4

现在以下内容非常适合单个查找和替换一个单词。

find path/to/folder/ -maxdepth 3 -name '*.*' -execdir bash -c 'mv -i "$1" "${1//foo/}"' bash {} \;

我也尝试了多个发现,但这似乎是一个很长的路要走,而且我似乎遇到了这样的问题。

我有几个问题:

  • 希望它不区分大小写
  • 需要“${1//foo/}”来引用列表
  • 如果大于 1,则删除空格

尝试在 cronjob 上将其作为 bash 脚本运行。

除非有更好的方法可以删除“This Awesome Content”-“30.9.2013.mp4”之间的所有内容。

非常感谢。

【问题讨论】:

    标签: linux bash unix find mv


    【解决方案1】:

    您可以使用“echo”命令将文件名作为变量访问。完成后,进行所需更改的最有效方法是使用“sed”。您可以使用“-e”标志将 sed 命令串在一起。作为 bash 中 for 循环的一部分,这一行为您提供了一个开始。您也可以在“查找”语句中使用这样的一行。

    echo $fyle | sed -e 's/FOO//gI' -e 's/BANG//gI'
    

    获得所需的文件名后,您可以将它们移回原来的名称。如果您需要更具体的说明,请告诉我。

    更新:这是一个更完整的解决方案。您必须将脚本调整为您自己的文件名等。

    for fyle in $(find . -name "*.*")
    do 
       mv -i $fyle `echo $fyle | sed -e 's/FOO//gI' -e 's/BANG//gI' `
    done
    

    最后,要用一个空白字符替换多个空白字符,您可以添加另一个 sed 命令。这是一个有效的命令:

    echo "file    input.txt" | sed 's/  */ /g'
    

    【讨论】:

    • 看来我是个新手。我将如何在我的 find 命令中实现它,替换 mv 命令?另外,如果我将 I 添加到 -e 's/FOO//g' 例如-e 's/FOO//Ig' 会忽略大小写。
    • 要使 sed 不区分大小写,请在末尾添加一个 gI。我已经更新了我的帖子。
    • 我添加了一个更完整的解决方案。请告诉我它是如何为您工作的。
    【解决方案2】:

    prename 可用于文件重命名部分。 stg 类似:

    find ... -exec prename 's/(deleteme1|deleteme2|…)//g' {} \;
    

    【讨论】:

      【解决方案3】:

      执行此操作的一种方法是添加一个中间步骤,在该步骤中使用mv 命令生成文件以实现此目的,然后执行该文件。我假设您有一个 words_file 文件,其中包含您不想要的字词。

      cd 开始之前的文件夹

      # Create list of valid <file>s in file_list, and list of "mv <file> " commmands
      # in cmd_file
      ls | grep -f words_file | tee file_list | sed 's/\(.*\)/mv "\1" /g' > cmd_file
      
      # Create the sed statements using the words_file, store it to sed_commands
      # Then, apply the sed commands to file_list
      sed 's/\(.*\)/s\/\1\/\/g/g' words_file > sed_commands
      sed -f sed_commands file_list > new_file_names
      
      # Combine cmd_file and new_file_names to produce the full mv statements
      paste cmd_file new_file_names > final_cmds
      
      # To verify the commands
      cat final_cmds
      
      # Finally, execute it
      sh final_cmds
      

      这是我能想到的,它避免了为每个单词手动编写sed -e。不确定是否有使用常见 bash 实用程序的更简单方法。当然,你可以使用perl或者python,写的更简洁。

      编辑:简化它,去掉 eval 和 xargs。

      【讨论】:

      • 看起来不错,如何指定文件夹?
      • 运行此“$ sed 's/(.*)/s\/\1\/\/g' words_file > sed_commands”时出现错误----错误是:sed : -e 表达式 #1, char 19: 未终止的 `s' 命令
      • @Keelan cd 到开始之前的目录。
      • @Hari Shankar 这是递归的吗?
      • @Keelan 否,但可以通过将第一行中的 ls 更改为 find . 使其递归
      【解决方案4】:

      任务的 脚本。它至少接受两个参数,第一个是要从文件名中删除的单词列表,其余的是要处理的文件:

      perl -MFile::Spec -MFile::Copy -e '
          $words = join( q{|}, split( q| |, shift ) );
          $words_re = qr{$words}i;
          for $path ( @ARGV ) {
              ($dummy, $dir, $f) = File::Spec->splitpath( $path );
              $f =~ s/$words_re//g;
              $f =~ s/\s{2,}/ /g;
              $newpath = File::Spec->catfile( $dir, $f );
              move( $path, $newpath );
              printf qq|[[%s]] renamed to [[%s]]\n|, $path, $newpath;
          }
      ' "720p BLAH FOO BANG OOO" tmp/user/*.mp4
      

      在我的测试中,我有以下输出:

      [[tmp/user/This Awesome Content 720p BLAH FOO BANG OOO - 30.9.2013.mp4]] renamed to [[tmp/user/This Awesome Content - 30.9.2013.mp4]]
      

      【讨论】:

      • 我根本不懂 perl,所以我认为这可能超出了我的范围。我可以指定一个目录来搜索文件吗?
      • @Keelan:是的。但是随后使用替代命令是危险的,因为可以修改部分路径。使用模块需要修复。
      • 我得到一堆编译错误,并且在操作员预期的地方找到了字符串。我推测,当我复制和粘贴时,格式很可能是错误的。
      • @Keelan:你对脚本的论点是什么?
      • 虽然我更改了路径,但您输入的内容逐字逐句。 pastebin.com/raw.php?i=mNgEmzFD
      猜你喜欢
      • 2016-01-19
      • 2021-12-29
      • 2016-02-11
      • 1970-01-01
      • 2018-09-28
      • 1970-01-01
      • 2017-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多