linux cp 和 mv 中的通配符用法
linux wildcard usage in cp and mv
我正在编写一个脚本来处理 20 个文件。它们都位于不同的目录中。我有部分文件名。
- 在日志目录中,File1_Date_time.err更改为File1__Date_time_orig.err
- cd ../脚本/
- 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)
#!/bin/bash
INPUT=
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也得到了类似的反馈
我做的对吗?
谢谢!
花一分钟时间谈谈通配符的工作原理。
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 在添加新名称之前去除旧名称的尾部。
试试这个:
更改这些:
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 "${var1}113_${f#$var1}";
done
find
命令可以在您想要对通配符(或更复杂的)文件名匹配执行操作的简单情况下非常简洁地使用。下面的技巧可以提交记忆……差不多!
这通过让 find
命令 运行 对它找到的每个文件名的另一个命令来工作。您可以使用 echo
代替 mv
前面的 of/in 干 运行 这个例子。
如果我们想将当前目录中名称以 'report' 开头的所有文件移动到另一个名为 'reports' 的并行目录:
find . -name "report*.*" -exec mv '{}' ../reports/ \;
通配符字符串必须用引号引起来,标记文件名 'found' 的 {} 必须用引号引起来,最后的分号必须转义 - 所有这些都是由于 Bash/shell 处理这些字符。
查看 find
的手册页以了解更多用途:https://linux.die.net/man/1/find
我用的就是这个,写起来很快就记住了
复制:
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{}
使 {}
成为 占位符
使用 awk 和 sed
使用 ls 过滤,使用 awk 为每条记录构建移动命令,最后 sed 'e' 将执行命令。
ls *.avro | awk ' { print "mv "" aa_" }' | sed 'e'
首先尝试不使用 sed -- 一旦您知道您的命令正确显示,请添加 sed。
我正在编写一个脚本来处理 20 个文件。它们都位于不同的目录中。我有部分文件名。
- 在日志目录中,File1_Date_time.err更改为File1__Date_time_orig.err
- cd ../脚本/
- 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)
#!/bin/bash
INPUT=
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也得到了类似的反馈
我做的对吗?
谢谢!
花一分钟时间谈谈通配符的工作原理。
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 在添加新名称之前去除旧名称的尾部。
试试这个:
更改这些:
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 "${var1}113_${f#$var1}";
done
find
命令可以在您想要对通配符(或更复杂的)文件名匹配执行操作的简单情况下非常简洁地使用。下面的技巧可以提交记忆……差不多!
这通过让 find
命令 运行 对它找到的每个文件名的另一个命令来工作。您可以使用 echo
代替 mv
前面的 of/in 干 运行 这个例子。
如果我们想将当前目录中名称以 'report' 开头的所有文件移动到另一个名为 'reports' 的并行目录:
find . -name "report*.*" -exec mv '{}' ../reports/ \;
通配符字符串必须用引号引起来,标记文件名 'found' 的 {} 必须用引号引起来,最后的分号必须转义 - 所有这些都是由于 Bash/shell 处理这些字符。
查看 find
的手册页以了解更多用途:https://linux.die.net/man/1/find
我用的就是这个,写起来很快就记住了
复制:
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{}
使 {}
成为 占位符
使用 awk 和 sed
使用 ls 过滤,使用 awk 为每条记录构建移动命令,最后 sed 'e' 将执行命令。
ls *.avro | awk ' { print "mv "" aa_" }' | sed 'e'
首先尝试不使用 sed -- 一旦您知道您的命令正确显示,请添加 sed。