How do you run a command for each line of a file?

2019-01-07 04:10发布

For example, right now I'm using the following to change a couple of files whose Unix paths I wrote to a file:

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

Is there a more elegant, safer way?

8条回答
趁早两清
2楼-- · 2019-01-07 04:44

I see that you tagged bash, but Perl would also be a good way to do this:

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

You could also apply a regex to make sure you're getting the right files, e.g. to only process .txt files:

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

To "preview" what's happening, just replace the backticks with double quotes and prepend print:

perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
查看更多
你好瞎i
3楼-- · 2019-01-07 04:46

If your file is not too big and all files are well named (without spaces or other special chars like quotes), you could simply:

chmod 755 $(<file.txt)

If you have special chars and/or a lot of lines in file.txt.

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

if your command need to be run exactly 1 time by entry:

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

This is not needed for this sample, as chmod accept multiple files as argument, but this match the title of question.

For some special case, you could even define location of file argument in commands generateds by xargs:

xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
查看更多
Bombasti
4楼-- · 2019-01-07 04:46

If you know you don't have any whitespace in the input:

xargs chmod 755 < file.txt

If there might be whitespace in the paths, and if you have GNU xargs:

tr '\n' '\0' < file.txt | xargs -0 chmod 755
查看更多
Explosion°爆炸
5楼-- · 2019-01-07 04:50

If you want to run your command in parallel for each line you can use GNU Parallel

parallel -a <your file> <program>

Each line of your file will be passed to program as an argument. By default parallel runs as many threads as your CPUs count. But you can specify it with -j

查看更多
闹够了就滚
6楼-- · 2019-01-07 04:52

Yes.

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

This way you can avoid a cat process.

cat is almost always bad for a purpose such as this. You can read more about Useless Use of Cat.

查看更多
爷的心禁止访问
7楼-- · 2019-01-07 04:52

if you have a nice selector (for example all .txt files in a dir) you could do:

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

bash for loop

or a variant of yours:

while read line; do chmod 755 "$line"; done <file.txt
查看更多
登录 后发表回答