【问题标题】:Using mv command won't recognize * as wildcard使用 mv 命令不会将 * 识别为通配符
【发布时间】:2014-03-31 06:21:43
【问题描述】:

我有这个脚本,并且我知道其中的 awk 命令可以工作,但是当我想使用与使用 mv 命令执行任务的文件相同的名称保存输出时,* 是不用作通配符,而是用作字符,我最终得到一个名称如下的文件:

阿尔及利亚_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

【问题讨论】:

  • 您不能使用匹配多个文件的模式作为mv 命令的目标。 ${i}_*_sites.txt 应该代表什么单个文件?
  • 你刚才说的和阿努巴瓦说的一样。那有什么意义呢?
  • 这是一个超越任何特定答案的评论。
  • 无论如何,同样的 -exact- 评论在你之前发布了。如果它没有添加任何东西,那么你应该把它留给自己。这是一个可以提供帮助的网站。请记住这一点。
  • 当我看到问题本身存在问题时,我不会浏览答案以查看那里正在进行什么讨论。

标签: bash shell awk mv


【解决方案1】:

mv 命令无法识别* 通配符;外壳可以。

这个:

foo*.txt

扩展为当前目录中名称以foo 开头并以.txt 结尾的所有文件的列表。如果您将foo*.txt 作为参数传递给mv,则mv 命令永远不会看到*;它只看到文件列表。

这意味着如果你有文件foo1.txtfoo2.txt,这个:

mv foo*.txt bar*.txt

不会foo1.txt 重命名为 bar1.txtfoo2.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

【讨论】:

    【解决方案2】:

    问题是引用。 Glob 模式应该在引号之外,所以你需要:

    "${i}_"*"_sites.txt"
    

    【讨论】:

    • 我没有工作,我收到了这个可怕的消息:用法:mv [-f | -i | -n] [-v] 源目标 mv [-f | -i | -n] [-v] 源...目录
    • 如果 "${i}_"*"_sites.txt" 模式匹配超过 1 个文件,则 mv 将失败,因为目标只能是单个文件/目录。
    • 但我认为* 会让它匹配不同的文件。这不是这个通配符在做什么吗?浏览与模式"${i}_"*"_sites.txt" 匹配的所有不同文件
    • 如何保存与"${i}_"*"_sites.txt" 匹配的不同文件?
    • 查看"${i}_"*"_sites.txt" 不是mv 的源文件而是目标文件
    猜你喜欢
    • 2015-10-04
    • 2013-09-20
    • 2010-11-11
    • 2011-10-26
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 1970-01-01
    • 2011-11-19
    相关资源
    最近更新 更多