【问题标题】:rename specific pattern of files in bash在 bash 中重命名文件的特定模式
【发布时间】:2014-05-27 05:36:04
【问题描述】:

我有以下文件和目录:

/tmp/jj/
/tmp/jj/ese
/tmp/jj/ese/2010
/tmp/jj/ese/2010/test.db
/tmp/jj/dfhdh
/tmp/jj/dfhdh/2010
/tmp/jj/dfhdh/2010/rfdf.db
/tmp/jj/ddfxcg
/tmp/jj/ddfxcg/2010
/tmp/jj/ddfxcg/2010/df.db
/tmp/jj/ddfnghmnhm
/tmp/jj/ddfnghmnhm/2010
/tmp/jj/ddfnghmnhm/2010/sdfs.db

我想将所有 2010 目录重命名为其父目录,然后将 tar 所有 .db 文件重命名...

我尝试的是:

#!/bin/bash

if [ $# -ne 1 ]; then
    echo "Usage: `basename $0` <absolute-path>"
    exit 1
fi

if [ "$(id -u)" != "0" ]; then
    echo "This script must be run as root" 1>&2
    exit 1
fi
rm /tmp/test

find $1 >> /tmp/test
for line in $(cat /tmp/test)
do
    arr=$( (echo $line | awk -F"/" '{for (i = 1; i < NF; i++) if ($i == "2010") print $(i-1)}') )
    for index in "${arr[@]}"
    do
    echo $index #HOW TO WRITE MV COMMAND RATHER THAN ECHO COMMAND?
    done
done

1) 结果是:

ese


dfhdh


ddfxcg


ddfnghmnhm

但应该是:

ese
dfhdh
ddfxcg
ddfnghmnhm

2) 如何将所有 2010 目录重命名为其父目录? 我的意思是怎么做(我想在loop做,因为目录很多):

mv /tmp/jj/ese/2010 /tmp/jj/ese/ese
mv /tmp/jj/dfhdh/2010 /tmp/jj/dfhdh/dfhdh
mv /tmp/jj/ddfxcg/2010 /tmp/jj/ddfxcg/ddfxcg
mv /tmp/jj/ddfnghmnhm/2010 /tmp/jj/ddfnghmnhm/ddfnghmnhm

【问题讨论】:

    标签: arrays bash awk


    【解决方案1】:

    这应该很接近:

    find "$1" -type d -name 2010 -print |
    while IFS= read -r dir
    do
        parentPath=$(dirname "$dir")
        parentDir=$(basename "$parentPath")
        echo mv "$dir" "$parentPath/$parentDir"
    done
    

    测试后删除echo。如果您的目录名称可以包含换行符,请查看find-print0 选项和xargs-0 选项。

    【讨论】:

      【解决方案2】:

      可以使用grep -P:

      grep -oP '[^/]+(?=/2010)' file
      ese
      ese
      dfhdh
      dfhdh
      ddfxcg
      ddfxcg
      ddfnghmnhm
      ddfnghmnhm
      

      【讨论】:

        【解决方案3】:

        首先,只遍历您感兴趣的目录,并避免使用临时文件:

        for d in $(find $1 -type d -name '2010') ; do
        

        然后您可以使用basenamedirname 提取该目录名称的一部分并重建所需的名称。比如:

          b="$(dirname $d)"
          p="$(basename $b)"
          echo mv "$d" "$b/$p" 
        

        您可以使用 shell 字符串替换操作而不是 basename/dirname。

        【讨论】:

        • 不需要数组和awk?你的意思是我删除脚本并执行你的步骤?你能把整个剧本放上去吗?我现在没有linux机器...谢谢
        • 我认识我的朋友,但结果只是打印mv etc etc 我应该删除echo吗?
        • 在您测试并确认它有效之前,您不应该移除回声。
        • 优秀...很好的答案...我删除了 echo 然后它可以在我朋友的机器上运行...
        • 永远不要在目录/文件名上执行像 for d in $(find...); do ... done 这样的 for 循环,因为当它们包含空格时它会失败。始终使用 find ... | while IFS= read -r d; do ... done 代替。当它们包含换行符时仍然存在问题,但可能性要小得多,如果发生切换到find -print0 | xargs -0
        【解决方案4】:

        您可以改为使用find 来确定目录是否包含名为2010 的子目录并执行mv

        find /tmp -type d -exec sh -c '[ -d "{}"/2010 ] && mv "{}"/2010 "{}"/$(basename "{}")' -- {} \;
        

        我不确定您是否有任何其他问题,但这会执行您在问题末尾列出的内容,即:

        mv /tmp/jj/ese/2010 /tmp/jj/ese/ese
        

        等等……

        【讨论】:

        • 谢谢您..有两个问题...您的回答如何编辑我的脚本..您可以这样做吗?
        • @MortezaLSC 如果我正确理解了这个问题,那么您需要替换上面提到的find 命令中传递给脚本的第一个参数。
        • find{} 占位符不应该以这种方式使用。想象一下有一个文件,里面有一个引用和一个邪恶的命令,你就完蛋了! sh 命令中的所有 {} 都应替换为 $1
        猜你喜欢
        • 2017-09-19
        • 2021-09-20
        • 1970-01-01
        • 2020-03-27
        • 2015-05-05
        • 2020-12-26
        • 2011-12-13
        • 2020-02-18
        • 2017-07-28
        相关资源
        最近更新 更多