Answers:
这是因为不仅只有一个答案...
shell
命令行扩展xargs
专用工具while read
有一些评论while read -u
使用private fd
进行交互式处理(示例)关于OP要求:运行chmod
在文件中列出的所有目标,xargs
是指定的工具。但是对于其他一些应用程序,文件数量很少等。
如果您的文件不是太大,并且所有文件都命名正确(没有空格或其他特殊字符,如引号),则可以使用shell
命令行扩展。只是:
chmod 755 $(<file.txt)
对于少量文件(行),此命令较轻。
xargs
是正确的工具对于更大数量的文件,或输入文件中几乎任意数量的行...
对于许多binutils的工具,如chown
,chmod
,rm
,cp -t
...
xargs chmod 755 <file.txt
如果您在中有特殊字符和/或很多行file.txt
。
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
如果您的命令需要通过输入精确运行1次:
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)
seq 1 5
作为输入进行测试试试这个:
xargs -n 1 -I{} echo Blah {} blabla {}.. < <(seq 1 5)
Blah 1 blabla 1..
Blah 2 blabla 2..
Blah 3 blabla 3..
Blah 4 blabla 4..
Blah 5 blabla 5..
每行指挥官一次。
while read
和变体。正如OP所建议的那样cat file.txt | while read in; do chmod 755 "$in"; done
起作用,但是有两个问题:
cat |
是没用的叉子,并且
| while ... ;done
之后将成为环境消失的潜壳;done
。
因此,可以这样写:
while read in; do chmod 755 "$in"; done < file.txt
但,
可能会警告您$IFS
并read
标记:
help read
read: read [-r] ... [-d delim] ... [name ...] ... Reads a single line from the standard input... The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on... Only the characters found in $IFS are recognized as word delimiters. ... Options: ... -d delim continue until the first character of DELIM is read, rather than newline ... -r do not allow backslashes to escape any characters ... Exit Status: The return code is zero, unless end-of-file is encountered...
在某些情况下,您可能需要使用
while IFS= read -r in;do chmod 755 "$in";done <file.txt
为了避免出现奇怪的文件名问题。也许如果您遇到麻烦UTF-8
:
while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txt
当您STDIN
用于阅读时file.txt
,您的脚本无法进行交互(无法再使用STDIN
)。
while read -u
,使用专用fd
。语法:while read ...;done <file.txt
将重定向STDIN
到file.txt
。这意味着,您将无法处理流程,直到流程完成。
如果计划创建交互式工具,则必须避免使用,STDIN
而应使用其他替代文件描述符。
常量文件描述符为:0
用于STDIN,1
用于STDOUT和2
用于STDERR。您可以通过以下方式查看它们:
ls -l /dev/fd/
要么
ls -l /proc/self/fd/
从那里,您必须在0
和之间选择未使用的数字63
(实际上,更多信息取决于sysctl
超级用户工具)作为文件描述符:
对于此演示,我将使用fd 7
:
exec 7<file.txt # Without spaces between `7` and `<`!
ls -l /dev/fd/
然后,您可以使用read -u 7
这种方式:
while read -u 7 filename;do
ans=;while [ -z "$ans" ];do
read -p "Process file '$filename' (y/n)? " -sn1 foo
[ "$foo" ]&& [ -z "${foo/[yn]}" ]&& ans=$foo || echo '??'
done
if [ "$ans" = "y" ] ;then
echo Yes
echo "Processing '$filename'."
else
echo No
fi
done 7<file.txt
done
关闭fd/7
:
exec 7<&- # This will close file descriptor 7.
ls -l /dev/fd/
注意:我使用标准版本,因为在使用并行过程执行许多I / O时,此语法可能很有用:
mkfifo sshfifo
exec 7> >(ssh -t user@host sh >sshfifo)
exec 6<sshfifo
cat file.txt | tr \\n \\0 | xargs -0 -n1 chmod 755
tr \\n \\0 <file.txt |xargs -0 [command]
比您描述的方法快约50%。
是。
while read in; do chmod 755 "$in"; done < file.txt
这样,您可以避免一个cat
过程。
cat
是一个好主意,但在这种情况下,在指定的命令是xargs
chmod
(即,实际上为文件中的每一行运行一个命令)。
如果您有一个不错的选择器(例如,目录中的所有.txt文件),则可以执行以下操作:
for i in *.txt; do chmod 755 "$i"; done
或您的变体:
while read line; do chmod 755 "$line"; done <file.txt
如果您知道输入中没有空格,请执行以下操作:
xargs chmod 755 < file.txt
如果路径中可能有空格,并且您有GNU xargs:
tr '\n' '\0' < file.txt | xargs -0 chmod 755
xargs
健壮。这个工具很老,他的代码也被重新审视。他的目标是最初建立关于shell限制的行(64kchar /行或诸如此类)。现在,此工具可以处理非常大的文件,并且可以减少到最终命令的派生次数。查看我的答案和/或man xargs
。
brew install findutils
)在macOS上安装GNU xargs ,然后调用GNU xargs gxargs
,例如gxargs chmod 755 < file.txt
如果要为每行并行运行命令,则可以使用GNU Parallel
parallel -a <your file> <program>
文件的每一行将作为参数传递给程序。默认情况下,parallel
运行的线程数与CPU数量相同。但是你可以用-j
我看到您标记了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
chmod
功能
perl -lpe 'chmod 0755, $_' file.txt
- -l
用于“自动
您还可以使用AWK,它可以为您提供更大的灵活性来处理文件
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
如果您的文件具有字段分隔符,例如:
栏位1,栏位2,栏位3
仅获取第一个字段
awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt
您可以在GNU文档https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple中查看更多详细信息
该逻辑适用于许多其他目标。以及如何从/ 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
xargs
最初为满足这种需求而构建时一样,某些功能(例如,在当前环境中尽可能长地构建命令以chmod
在这种情况下尽可能少地调用),减少派生确保了效率。while ;do..done <$file
暗示对1个文件运行1个fork。xargs
可以以一种可靠的方式运行一千个文件的fork。