迭代目录中的所有文件,或仅覆盖sh中的指定文件

时间:2014-05-23 08:40:58

标签: bash shell

我有一个目录config,其中包含以下文件:

$ ls config
file one
file two
file three

我想要一个bash脚本,当没有参数时,它会迭代所有这些文件;当给定文件名作为参数时,我希望它迭代命名文件。

#!/bin/sh
for file in ${@:-config/*}
do
    echo "Processing '$file'"
done

如上所述,for循环中列表术语没有引号,它在无参数情况下产生预期输出,但在传递参数时断开(它在空格上分割文件名。)引用列表term(for file in "${@:-config/*}")在我传递文件名时起作用,但如果不这样做则无法扩展glob。

有没有办法让两种情况都有效?

3 个答案:

答案 0 :(得分:3)

对于更简单的解决方案,只需修改IFS变量

即可
#!/bin/bash
IFS=''
for file in ${@:-config/*}
do
    echo "Processing '$file'"
done
IFS=$' \n\t'

$IFS是一个默认的shell变量,它列出了shell使用的所有分隔符。如果从此列表中删除空格,则shell将不再分割为空格。您应该在运行后将其设置回默认值,这样它就不会导致其他函数在您的脚本中稍后行为错误

注意:这似乎与破坏行为不一致(我使用了debian,以及#!/bin/sh指向破折号的链接)。如果使用空$IFS,则传递的args将仅返回1个文件。但是,如果您输入一些随机值(即IFS=':'),行为将是您想要的行为(除非您的文件名中有:

这适用于#!/bin/bash,但

答案 1 :(得分:2)

如果没有给出位置参数,则显式设置;然后for循环对于两种情况都是相同的:

[ $# -eq 0 ] && set -- config/*
for file in "$@"; do
    echo "Processing '$file'"
done

答案 2 :(得分:1)

将处理代码放在一个函数中,然后使用不同的循环来调用它:

if [ $# -eq 0 ]
then for file in config/*
    do processing_func "$file"
done
else for file in "$@"
    do processing_func "$file"
done
fi