cp和mv中的linux通配符使用

Posted

技术标签:

【中文标题】cp和mv中的linux通配符使用【英文标题】:linux wildcard usage in cp and mv 【发布时间】:2016-06-13 00:29:48 【问题描述】:

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

    在日志目录中,File1_Date_time.err 更改为 File1__Date_time_orig.err cd ../scripts/ sh 文件.sh

File1 目录为 /data/data1directory/Sample_File1/logs/File1_Data_time.err File2目录为/data/data2directory/Sample_File2/logs/File2_Data_time.err .....

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

#!/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 文件1 . runrunrun.sh 文件 1 sh runrunrun.sh 文件1

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

我做得对吗?

谢谢!

【问题讨论】:

mvcp没有通过您正在编写的通配符,如果这些通配符有任何有效的扩展。相反,它们被传递通过运行这些扩展创建的文字文件名。因此,由于他们不知道输入名称中使用的文字通配符,因此他们不可能将输入名称中的 * 映射到输出名称中的 * 如果你想编写重命名工具,BashFAQ #30 是一个不错的起点:mywiki.wooledge.org/BashFAQ/030 相关:***.com/questions/20629302/… 顺便说一句,sh foo.sh 非常危险,除非您绝对确定该脚本以 #!/bin/sh 而不是 #!/bin/bash#!/bin/ksh、@987654333 开头@, 等等;否则,它可能会使用错误的解释器。 【参考方案1】:

使用 awk 和 sed

使用 ls 过滤,使用 awk 为每条记录构建移动命令,最后的 sed 'e' 将执行该命令。

ls  *.avro  | awk '  print "mv "$1" aa_"$1 ' | sed 'e'

首先尝试不使用 sed -- 一旦您知道您的命令显示正确,请添加 sed。

【讨论】:

【参考方案2】:

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

这通过让find 命令在它找到的每个文件名上运行另一个命令来工作。您可以使用echo 代替/在mv 前面来试运行此示例。

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

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

通配符字符串必须用引号括起来,标记“找到”的文件名的 必须用引号括起来,最后的分号必须被转义 - 所有这些都是由于对这些字符的 Bash/shell 处理。

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

【讨论】:

如果多个文件的文件名相同,这个解决方案似乎会覆盖目标中的文件。如何复制整个文件夹结构? 第一个答案涵盖了我的情况。我还使用 cp --parents ============================= for f in ./*/*20220202.csv;做 cp -rfv --parents "$f" "/projects/drprojects/evmc/tempo4/" 完成 代码只是一个例子。原来的问题也有这个问题。问一个单独的问题,或者解决它!【参考方案3】:

这是我用的,写起来很快,记起来也很快

复制:

ls -1 *.txt | xargs -L1 -I cp  .old 

搬家:

ls -1 *.txt | xargs -L1 -I mv  .old 

解释:

xargs(1) -L1 -I  

从标准输入构建和执行命令行

-L max-lines
       Use  at most max-lines nonblank input lines per command line.  Trailing blanks cause an input line
       to be logically continued on the next input line.  Implies -x.

-I replace-str
       Replace occurrences of replace-str in the initial-arguments with names read from  standard  input.
       Also,  unquoted  blanks  do  not  terminate  input  items;  instead  the  separator is the newline
       character.  Implies -x and -L 1.

基本上与-L1 一起发送参数,-I 使 成为占位符

【讨论】:

带有有趣文件名的越野车。一般来说, xargs 只有在 NUL 分隔的输入和 -0 参数下才是安全的;默认行为将输入拆分为空格,而不仅仅是换行符(尽管换行符也不安全,因为它们在文件名中是允许的);将引号字符视为语法而不是文字数据;否则通常会输入。 另见Why you shouldn't parse the output of ls【参考方案4】:

让我们来谈谈通配符的工作原理。

cp *.txt foo

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

cp a.txt b.txt c.txt foo

类似

mv *.txt *.old

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

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

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

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

因此,您需要使用不同的工具。考虑:

# 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

这使用parameter expansion 在添加新名称之前去除旧名称的尾部。

【讨论】:

从 2020 年开始,GNU bash 5.0 及更高版本不再是这种情况 @user164863,请提供相反的演示。 mvcp 不是 bash 本身的一部分,它们由您的操作系统供应商提供,并且 glob 在调用之前已经扩展;这些都没有改变。【参考方案5】:

试试这个:

改变这些:

zc_cd_delim_01.csv
zc_cd_delim_04.csv

进入这些:

zc_cd_delim_113_01.csv
zc_cd_delim_113_04.csv

命令行:

for f in zc_cd_delim_??.csv; do var1=$f%%??.*; 
    mv $f "$var1113_$f#$var1"; 
done

【讨论】:

mv "$f",而是 -- 如果?? 匹配带有空格的文件名,或者IFS 包含在名称中找到的字符(即_),否则行为可能会令人惊讶. 顺便说一句,我有点不清楚这如何适用于手头的问题——c_cd_delim_??.csv 在我看来并不像 OP 用作示例的模式之一他们想要匹配的东西。您介意编辑以使问题的适用性更清晰吗?

以上是关于cp和mv中的linux通配符使用的主要内容,如果未能解决你的问题,请参考以下文章

linux基本命令

Linux文件管理_1

linux学习总结

Linux基础

Linux的基础操作

如何在 Linux 中批量移动复制追加和重命名文件