【问题标题】:Bash command to move only some files?Bash命令只移动一些文件?
【发布时间】:2012-07-31 05:42:11
【问题描述】:

假设我的当前目录中有以下文件:

1.jpg
1original.jpg
2.jpg
2original.jpg
3.jpg
4.jpg

是否有终端/bash/linux 命令可以做类似的事情

if the file [an integer]original.jpg exists,
    then move [an integer].jpg and [an integer]original.jpg to another directory.

执行这样的命令会导致1.jpg、1original.jpg、2.jpg和2original.jpg在各自的目录下。

注意 这不必是一个命令。我可以是简单命令的组合。也许类似于将原始文件复制到新目录。然后对 newdir 中的文件进行一些正则表达式过滤,以从旧目录中获取仍然需要复制的文件名列表等。

【问题讨论】:

  • 这就是超级用户学习编程的原因:) 好问题。
  • 您是否需要担心可能存在5original.jpg 但没有5.jpg 的情况?

标签: linux bash shell


【解决方案1】:

启用扩展 glob 支持将允许您编写类似正则表达式的模式。这可以处理具有多位整数的文件,例如“87.jpg”和“87original.jpg”。然后可以使用 Bash 参数扩展从找到的文件的名称中去除“原始”,以便将两个相关文件一起移动。

shopt -s extglob
for f in +([[:digit:]])original.jpg; do
    mv $f ${f/original/} otherDirectory
done

在扩展模式中,+( x ) 匹配括号内的一个或多个内容,类似于正则表达式 x+。这里,x 是任意数字。因此,我们匹配当前目录中名称由 1 个或多个数字后跟“original.jpg”组成的所有文件。

${f/original/}bash 的模式替换示例。它从f 的值中删除字符串“original”的第一次出现。所以如果f是字符串“1original.jpg”,那么${f/original/}就是字符串“1.jpg”。

【讨论】:

    【解决方案2】:

    嗯,不是直接的,但它是一个单线器(编辑:不再):

    for i in [0-9].jpg; do
      orig=${i%.*}original.jpg
      [ -f $orig ] && mv $i $orig another_dir/
    done
    

    编辑:也许我应该指出我的解决方案:

    • for i in [0-9].jpg:为每个jpg文件执行循环体,文件名是一个数字。将整个文件名存储在$i
    • orig={i%.*}original.jpg:将“原始文件”的可能文件名保存在$orig
    • [ -f $orig ]:通过test(1)[ ... ] 的东西)检查$i 的原始文件是否存在。如果是,请将两个文件移至another_dir。这是通过&& 完成的:只有在测试成功时才会执行后面的部分。

    【讨论】:

    • 您应该将代码格式化为多行,以便于阅读。此外,您可以避免将 basename 与 ${i##*/} 一起使用。
    • 谢谢。避免使用基本名称并使用模式匹配是个好主意,但${i##*/} 对我不起作用。我改用${i%.*}
    【解决方案3】:

    这应该适用于任何严格的数字前缀,即234.jpg

    for f in *original.jpg; do
      pre=${f%original.jpg}
      if [[ -e "$pre.jpg" && "$pre" -eq "$pre" ]] 2>/dev/null; then
        mv "$f" "$pre.jpg" targetDir
      fi
    done
    

    "$pre" -eq "$pre" 如果不是整数则报错

    编辑:
    如果同时存在 original.jpg.jpg 这将失败。
    $pre 为空字符串,"$pre" -eq "$pre" 为真。

    【讨论】:

      【解决方案4】:

      以下内容可行且易于理解(将out 替换为输出目录,将{1..9} 替换为您的数字的实际范围。

      for x in {1..9}
      do
      if [ -e ${x}original.jpg ]
      then
      mv $x.jpg out
      mv ${x}original.jpg out
      fi
      done
      

      你显然也可以单行输入。

      【讨论】:

        【解决方案5】:

        您可以使用 Regex 语句在您正在查看的文件名中查找“匹配项”。然后对找到的“匹配项”执行操作。

        【讨论】:

        • 谢谢,你能根据上面给出的文件名展示一个示例解决方案吗?我从查看示例解决方案中学到了最好的东西
        【解决方案6】:

        integer=0; while [ $integer -le 9 ] ; do if [ -e ${integer}original.jpg ] ; then mv -vi ${integer}.jpg ${integer}original.jpg lol/ ; fi ; integer=$[ $integer + 1 ] ; done

        请注意,这里的“lol”是目标目录。您可以将其更改为您喜欢的任何内容。另外,您可以更改while [ $integer -le 9 ] 中的9 以检查大于9 的整数。现在它从0* 开始,在检查9* 后停止。

        编辑:如果你愿意,你可以用回车替换我代码中的分号,这样可能更容易阅读。此外,您可以通过这种方式将整个块粘贴到终端中,即使这可能不是很明显。

        【讨论】:

        • 您应该考虑以一种易于阅读和维护的方式格式化您的代码。
        猜你喜欢
        • 2015-06-24
        • 1970-01-01
        • 2014-10-05
        • 2011-09-14
        • 1970-01-01
        • 2019-07-13
        • 2018-02-16
        • 1970-01-01
        • 2015-12-23
        相关资源
        最近更新 更多