我有这个脚本,我知道它中的awk命令有效,但是当我想使用与mv
命令*
命令执行任务的文件相同的名称来保存输出时{{ 1}}不是用作通配符而是用作字符,我最终得到一个名称如下的文件:
Algeria_BER _ * _ sites.txt
剧本:
#!/bin/bash
for i in Algeria_BER
do
echo awk 'FNR==NR{a[++i]=$0;next} {print a[FNR] RS $0}' \
reduced_filt_MAF_b37_chr1_${i}_ldhat.txt_names ${i}_*_sites.txt > $$.tmp &&
mv $$.tmp "${i}_*_sites.txt"
done
答案 0 :(得分:4)
问题在引用。 Glob模式应该在引用之外,因此您需要:
"${i}_"*"_sites.txt"
答案 1 :(得分:4)
mv
命令无法识别*
通配符; shell确实。
此:
foo*.txt
展开到当前目录中名称以foo
开头并以.txt
结尾的所有文件的列表。如果您将foo*.txt
作为参数传递给mv
,则mv
命令永远不会看到*
;它只能看到文件列表。
这意味着如果您有文件foo1.txt
和foo2.txt
,请执行以下操作:
mv foo*.txt bar*.txt
将不将foo1.txt
重命名为bar1.txt
,将foo2.txt
重命名为bar2.txt
- 因为bar*.txt
只能展开到列表已存在的文件 。如果没有匹配bar*.txt
的现有文件,则上述内容扩展为:
mv foo1.txt foo2.txt bar42.txt
除非bar42.txt
恰好是目录,否则这是一个错误。它将以各种其他方式扩展,具体取决于当前存在的文件 - 并且它们都不可能是您想要的。
如果没有匹配给定通配符的文件,则行为取决于shell和您当前的设置。在bash
中,使用默认设置时,通配符不会展开 - 这可能是您获取名称中包含*
的文件的原因。
有批量重命名工具可以做你想要的(我自己没有用过)。
我经常使用的另一种方法是将文件列出到文本文件,手动编辑文件,然后将其作为脚本运行。例如,我可能会这样做:
ls foo*.txt > tmp
然后手动编辑tmp
以将每一行转换为执行我想要的命令:
foo1.txt
foo2.txt
- >
mv foo1.txt bar1.txt
mv foo2.txt bar2.txt
然后运行命令:
. ./tmp