如何为文件的每一行运行命令?

时间:2012-12-18 18:17:25

标签: bash loops batch-file line

例如,现在我正在使用以下内容来更改我写入文件的Unix路径的几个文件:

cat file.txt | while read in; do chmod 755 "$in"; done

有更优雅,更安全的方式吗?

10 个答案:

答案 0 :(得分:129)

while read in; do chmod 755 "$in"; done < file.txt

这样您就可以避免cat进程。

对于像这样的目的,

cat几乎总是不好的。您可以阅读有关 Useless Use of Cat.

的更多信息

答案 1 :(得分:85)

如果您的文件不是太大而且所有文件都命名为(没有空格或其他特殊字符,如引号),您可以简单地说:

chmod 755 $(<file.txt)

如果file.txt中有特殊字符和/或许多行。

xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)

如果您的命令需要通过条目正好运行一次:

xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)

此示例不需要这样,因为chmod接受多个文件作为参数,但这与问题标题匹配。

对于某些特殊情况,您甚至可以在xargs生成的命令中定义文件参数的位置:

xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)

答案 2 :(得分:13)

如果你有一个好的选择器(例如dir中的所有.txt文件) 你可以这样做:

for i in *.txt; do chmod 755 "$i"; done

bash for loop

或您的变体:

while read line; do chmod 755 "$line"; done <file.txt

答案 3 :(得分:13)

如果您知道输入中没有任何空格:

xargs chmod 755 < file.txt

如果路径中可能有空格,并且你有GNU xargs:

tr '\n' '\0' < file.txt | xargs -0 chmod 755

答案 4 :(得分:10)

如果您想为每一行并行运行命令,可以使用GNU Parallel

parallel -a <your file> <program>

您文件的每一行都将作为参数传递给程序。默认情况下,parallel运行与CPU计数一样多的线程。但您可以使用-j

指定它

答案 5 :(得分:2)

我看到你标记了bash,但Perl也是一个很好的方法:

perl -p -e '`chmod 755 $_`' file.txt

您还可以应用正则表达式以确保获得正确的文件,例如只处理.txt文件:

perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt

要“预览”正在发生的事情,只需用双引号替换反引号并添加print

perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt

答案 6 :(得分:1)

现在 xargs 仍然是这个问题的答案,但是……您现在可以使用 -a 选项直接从文件中读取输入:

xargs -a file.txt -n 1 -I {} chmod 775 {}

答案 7 :(得分:0)

您还可以使用AWK,它可以为您提供更大的灵活性来处理文件

ThisRibbonCollection

如果您的文件具有字段分隔符,例如:

  

field1,field2,field3

要仅获取第一个字段

namespace root-namespace
{
    partial class ThisRibbonCollection
    {
        internal forms.ELRibbon Ribbon1
        {
            get { return this.GetRibbon<forms.ELRibbon>(); }
        }
    }
}

您可以查看有关GNU文档的更多详细信息 https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple

答案 8 :(得分:0)

该逻辑适用于许多其他目标。 以及如何从/ home /文件系统读取每个用户的.sh_history?如果有一千个怎么办?

#!/bin/ksh
last |head -10|awk '{print $1}'|
 while IFS= read -r line
 do
su - "$line" -c 'tail .sh_history'
 done

这是脚本https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh

答案 9 :(得分:0)

我知道已经晚了,但仍然

如果您碰巧遇到了用\r\n而不是\n进入Windows保存的文本文件的情况,那么如果您的命令在读取行之后有某条命令作为参数,则可能会混淆输出。因此,请删除\r,例如:

cat file | tr -d '\r' | xargs -L 1 -i echo do_sth_with_{}_as_line