【问题标题】:find command on file name在文件名上查找命令
【发布时间】:2014-01-21 11:32:45
【问题描述】:

我有一个文件夹,里面有这样的图片:

395629_1365148250.png
395629_1365148251.png
395629_1365148252.png
395629_1365148253.png
395629_1365148254.png
415678_1387545677.png
429651_1390056123.png
429651_1390056124.png
429651_1390056125.png
522600_1389607024.png
529485_1389879560.png

名称是这样的:USERID_DATE.png。

我的目标是删除每个 USERID 的所有旧图像并只保留最后一个。

例如我需要删除这些:

395629_1365148250.png
395629_1365148251.png
395629_1365148252.png
395629_1365148253.png

并保留这个。

395629_1365148254.png

如果每个用户只有一张图片,我必须保留该图片。

我在这方面工作了很长时间,但我能够做到这一点。我使用了“find”命令,但我在 bash linux 命令方面不是很好,反正也不是那么好。

可能是 stackoverflow 不适合发布这种需求。在这种情况下,请见谅。

【问题讨论】:

    标签: bash command find


    【解决方案1】:

    似乎基本排序对此应该没问题。所以就做类似的事情

    #!/bin/bash
    for i in $(echo *_*.png | sort); do
      current="$i"
      [[ $current != "" ]] && [[ $last != "" ]] && [[ ${current%%_*} == ${last%%_*} ]] && rm "$last"
      last="$current"
    done          
    

    例如

    $ ls -1
    395629_1365148250.png
    395629_1365148251.png
    395629_1365148252.png
    395629_1365148253.png
    395629_1365148254.png
    415678_1387545677.png
    429651_1390056123.png
    429651_1390056124.png
    429651_1390056125.png
    522600_1389607024.png
    529485_1389879560.png
    $ ./script
    $ ls -1
    395629_1365148254.png
    415678_1387545677.png
    429651_1390056125.png
    522600_1389607024.png
    529485_1389879560.png
    

    如果您希望它在 bash 4+ 中是递归的,您可以将其更改为

    ...
    shopt -s globstar
    for i in $(echo **/*_*.png | sort)
    ...
    

    虽然在这种情况下,我肯定会确保在删除任何内容之前检查我们是否正在处理 number_number.png。

    【讨论】:

    • 来自 OP 的引述:»… for each userid …«
    • @Alfe 是的,误读了 OP。仍然不确定我完全理解他想要什么,但已编辑
    • 这很简单。他只想保留每个用户 ID 的最新图像。所有其他文件都将被删除。
    • @BroSlow:阿尔夫是对的。我只需要保留每个用户 ID 的最新图像。在您的代码中,图像 429651_* 仍然存在。
    • @BroSlow:我的终端告诉我:../action.sh:第 6 行:${i&&_}:替换错误。应该是 ${i%%_} ,不是吗?
    【解决方案2】:

    我相信图像是您想要的顺序,因为日期在不断增加(自 1970 年以来的刻度)。

    所以试试这个,并将 echo 换成实际的命令。

    注意我是在 OS X 上测试的,所以你 sed 可能不喜欢 -E 选项 nvm,Linux 上的 -E 选项也可以。很抱歉造成混乱

    还要注意最后一个文件总是被保留,因为它总是最后一个用户的最新文件,所以它甚至没有一行输出

    #!/bin/bash
    
    OLDU="X"
    for file in *.png; do
       NEWU=`echo $file|sed -E 's/(......)_.*/\1/g'`
       if [ $NEWU != $OLDU -a $OLDU != X ]; then
          echo keeping $OLDF
       else
          if [ $OLDU != X ]; then
             echo rm $OLDF
          fi
       fi
       OLDF=$file
       OLDU=$NEWU
    done
    

    生产

    rm 395629_1365148250.png
    rm 395629_1365148251.png
    rm 395629_1365148252.png
    rm 395629_1365148253.png
    keeping 395629_1365148254.png
    keeping 415678_1387545677.png
    rm 429651_1390056123.png
    rm 429651_1390056124.png
    keeping 429651_1390056125.png
    keeping 522600_1389607024.png
    

    【讨论】:

      【解决方案3】:

      循环遍历每个用户 ID(您可能有一个列表,所以我不会通过将它们从文件名中取出来解决该问题),然后按降序列出该用户 ID 的所有文件(最新的在前),然后使用tail 获取除最顶层之外的所有内容,使用rm 获取所有这些内容:

      for userid in $userids
      do
        rm $(find /path/to/my/images -name "$userid_*.png" -print | sort -r | tail -n +2)
      done
      

      如果这些内部列表非常大:

      for userid in $userids
      do
        find /path/to/my/images -name "$userid_*.png" -print | sort -r | tail -n +2 |
          while read oldFile
          do
            rm "$olfFile"
          done
      done
      

      要从文件名中查找所有用户标识,只有您可以使用:

      userids=$(find /path/to/my/images -name "*_*.png" -print | sed 's/_.*//' | sort -u)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-07
        • 1970-01-01
        • 1970-01-01
        • 2019-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多