关于shell:cp和mv中的Linux通配符用法

linux wildcard usage in cp and mv

我正在编写一个脚本来处理20个文件。 它们全部位于不同的目录中。 我有部分文件名。

  • 在日志目录中,File1_Date_time.err更改为File1__Date_time_orig.err
  • cd ../scripts/
  • sh File.sh
  • File1目录为/data/data1directory/Sample_File1/logs/File1_Data_time.err
    File2目录为/data/data2directory/Sample_File2/logs/File2_Data_time.err
    .....

    我的脚本看起来像这样。 (runrunrun.sh)

    1
    2
    3
    4
    5
    #!/bin/bash
    INPUT=$1
    mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
    cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
    sh /data/*/Sample_*/scripts/*_orig.sh

    运行时,我尝试过。
    ./runrunrun.sh File1
    。 runrunrun.sh File1
    sh runrunrun.sh File1

    mv:无法移动/data/data1directory/Sample_File1/logs/File1_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err:无此类文件或目录
    cp也得到了类似的反馈

    我做对了吗?

    谢谢!


    让我们谈论通配符如何工作一分钟。

    1
    cp *.txt foo

    如果存在与该glob匹配的文件,则实际上不使用参数*.txt调用cp。相反,它运行如下所示的内容:

    1
    cp a.txt b.txt c.txt foo

    同样,类似

    1
    mv *.txt *.old

    ...可能不知道该怎么办,因为调用它时,所看到的是:

    1
    mv a.txt b.txt c.txt *.old

    或者更糟糕的是,如果您已经有一个名为z.old的文件,它将看到:

    1
    mv a.txt b.txt c.txt z.old

    因此,您需要使用其他工具。考虑:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    # REPLACES: mv /data/*/Sample_*/logs/*_Data_time.err /data/*/Sample_*/logs/*_Data_time_orig.err
    for f in /data/*/Sample_*/logs/*_Data_time.err; do
      mv"$f""${f%_Data_time.err}_Data_time_orig.err"
    done

    # REPLACES: cp /data/*/Sample_*/scripts/*.sh /data/*/Sample_*/scripts/*_orig.sh
    for f in /data/*/Sample_*/scripts/*.sh; do
      cp"$f""${f%.sh}_orig.sh"
    done

    # REPLACES: sh /data/*/Sample_*/scripts/*_orig.sh
    for f in /data/*/Sample_*/scripts/*_orig.sh; do
      if [[ -e"$f" ]]; then
        # honor the script's shebang and let it choose an interpreter to use
       "$f"
      else
        # script is not executable, assume POSIX sh (not bash, ksh, etc)
        sh"$f"
      fi
    done

    这使用了参数扩展来去除旧名称的末尾,然后再添加新名称名称。


    在想要对通配符(或更复杂的)文件名匹配执行操作的简单情况下,可以非常简洁地使用find命令。以下技术可以用于内存...几乎!

    通过让find命令在找到的每个文件名上运行另一个命令来起作用。您可以使用echo代替mv空运行此示例。

    如果我们想将当前目录中所有以" report"开头的文件移动到另一个并行目录" reports":

    1
    find . -name"report*.*" -exec mv '{}' ../reports/ \;

    通配符字符串必须用引号引起来,标记"找到"的文件名的{}必须用引号引起来,并且必须转义最后的分号-所有这些都是由于对这些字符进行了Bash / shell处理。

    请查看find的手册页以了解更多用途:https://linux.die.net/man/1/find


    尝试这个:

    更改这些:

    1
    2
    zc_cd_delim_01.csv
    zc_cd_delim_04.csv

    这些:

    1
    2
    zc_cd_delim_113_01.csv
    zc_cd_delim_113_04.csv

    命令行:

    1
    2
    3
    for f in zc_cd_delim_??.csv; do var1=${f%%??.*};
        mv $f"${var1}113_${f#$var1}";
    done