Câu trả lời:
Điều này là do không chỉ có 1 câu trả lời ...
shell mở rộng dòng lệnhxargs công cụ chuyên dụngwhile read với một số nhận xétwhile read -usử dụng chuyên dụng fd, để xử lý tương tác (mẫu)Về yêu cầu OP: chạy chmodtrên tất cả các mục tiêu được liệt kê trong tệp , xargslà công cụ được chỉ định. Nhưng đối với một số ứng dụng khác, số lượng tệp nhỏ, v.v ...
Nếu tệp của bạn không quá lớn và tất cả các tệp đều được đặt tên tốt (không có dấu cách hoặc ký tự đặc biệt khác như dấu ngoặc kép), bạn có thể sử dụng shellmở rộng dòng lệnh . Đơn giản:
chmod 755 $(<file.txt)
Đối với số lượng nhỏ tệp (dòng), lệnh này là nhẹ hơn.
xargs là công cụ phù hợpĐối với số lượng tệp lớn hơn hoặc gần như bất kỳ số lượng dòng nào trong tệp đầu vào của bạn ...
Đối với nhiều binutils công cụ, như chown, chmod, rm, cp -t...
xargs chmod 755 <file.txt
Nếu bạn có ký tự đặc biệt và / hoặc rất nhiều dòng trong file.txt.
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
nếu lệnh của bạn cần được chạy chính xác 1 lần bằng cách nhập:
xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)
Điều này là không cần thiết cho mẫu này, vì chmodchấp nhận nhiều tệp làm đối số, nhưng điều này phù hợp với tiêu đề của câu hỏi.
Đối với một số trường hợp đặc biệt, bạn thậm chí có thể xác định vị trí của đối số tệp trong các lệnh được tạo bởi xargs:
xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
seq 1 5đầu vàoThử cái này:
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..
Trường hợp Commande được thực hiện một lần trên mỗi dòng .
while read và các biến thể.Theo đề xuất của OP cat file.txt | while read in; do chmod 755 "$in"; donesẽ hoạt động, nhưng có 2 vấn đề:
cat |là một ngã ba vô dụng , và
| while ... ;donesẽ trở thành một subshell nơi môi trường sẽ biến mất sau đó ;done.
Vì vậy, điều này có thể được viết tốt hơn:
while read in; do chmod 755 "$in"; done < file.txt
Nhưng,
Bạn có thể được cảnh báo $IFSvà readcờ:
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...
Trong một số trường hợp, bạn có thể cần phải sử dụng
while IFS= read -r in;do chmod 755 "$in";done <file.txt
Để tránh các vấn đề với tên tập tin lạ. Và có thể nếu bạn gặp sự cố với UTF-8:
while LANG=C IFS= read -r in ; do chmod 755 "$in";done <file.txtTrong khi bạn sử dụng STDINđể đọc file.txt, tập lệnh của bạn không thể tương tác (bạn không thể sử dụng STDINnữa).
while read -u, sử dụng chuyên dụng fd.Cú pháp: while read ...;done <file.txtsẽ chuyển hướng STDINđến file.txt. Điều đó có nghĩa là, bạn sẽ không thể xử lý quá trình cho đến khi họ hoàn thành.
Nếu bạn có kế hoạch tạo công cụ tương tác , bạn phải tránh sử dụng STDINvà sử dụng một số mô tả tệp thay thế .
Các mô tả tệp hằng là: 0cho STDIN , 1cho STDOUT và 2cho STDERR . Bạn có thể thấy chúng bằng cách:
ls -l /dev/fd/
hoặc là
ls -l /proc/self/fd/
Từ đó, bạn phải chọn số chưa sử dụng, giữa 0và 63(trên thực tế, tùy thuộc vào sysctlcông cụ siêu người dùng) làm mô tả tệp :
Đối với bản demo này, tôi sẽ sử dụng fd 7 :
exec 7<file.txt # Without spaces between `7` and `<`!
ls -l /dev/fd/
Sau đó, bạn có thể sử dụng read -u 7cách này:
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
Để đóng fd/7:
exec 7<&- # This will close file descriptor 7.
ls -l /dev/fd/
Nota: Tôi để striked phiên bản vì cú pháp này có thể là hữu ích, khi làm nhiều I / O với sự tương đồng xử lý:
mkfifo sshfifo
exec 7> >(ssh -t user@host sh >sshfifo)
exec 6<sshfifocat file.txt | tr \\n \\0 | xargs -0 -n1 chmod 755
tr \\n \\0 <file.txt |xargs -0 [command]nhanh hơn khoảng 50% so với phương pháp bạn mô tả.
Đúng.
while read in; do chmod 755 "$in"; done < file.txt
Bằng cách này bạn có thể tránh được một catquá trình.
cathầu như luôn luôn xấu cho một mục đích như thế này. Bạn có thể đọc thêm về Sử dụng Mèo vô dụng.
cat là một ý tưởng tốt, nhưng trong trường hợp này, các lệnh chỉ định làxargs
chmod(tức là thực sự chạy một lệnh cho mỗi dòng trong tệp).
read -rđọc một dòng duy nhất từ đầu vào tiêu chuẩn ( readkhông có -rdấu gạch chéo ngược, bạn không muốn điều đó)."
nếu bạn có một bộ chọn đẹp (ví dụ: tất cả các tệp .txt trong một thư mục) bạn có thể làm:
for i in *.txt; do chmod 755 "$i"; done
hoặc một biến thể của bạn:
while read line; do chmod 755 "$line"; done <file.txt
Nếu bạn biết bạn không có bất kỳ khoảng trắng nào trong đầu vào:
xargs chmod 755 < file.txt
Nếu có thể có khoảng trắng trong các đường dẫn và nếu bạn có GNU xargs:
tr '\n' '\0' < file.txt | xargs -0 chmod 755
xargslà mạnh mẽ. Công cụ này rất cũ và mã của anh ấy được xem xét lại mạnh mẽ . Mục tiêu của anh là khởi đầu để xây dựng các dòng liên quan đến các giới hạn về vỏ (64kchar / dòng hoặc một cái gì đó như vậy). Bây giờ công cụ này có thể làm việc với các tệp rất lớn và có thể giảm rất nhiều số ngã ba đến lệnh cuối cùng. Xem câu trả lời của tôi và / hoặc man xargs.
brew install findutils), và sau đó invoke xargs GNU với gxargsthay vào đó, ví dụgxargs chmod 755 < file.txt
Nếu bạn muốn chạy lệnh song song cho mỗi dòng, bạn có thể sử dụng GNU Parallel
parallel -a <your file> <program>
Mỗi dòng tệp của bạn sẽ được chuyển đến chương trình dưới dạng đối số. Theo mặc định, parallelchạy nhiều chủ đề như số lượng CPU của bạn. Nhưng bạn có thể chỉ định nó với-j
Tôi thấy rằng bạn đã gắn thẻ bash, nhưng Perl cũng sẽ là một cách tốt để làm điều này:
perl -p -e '`chmod 755 $_`' file.txt
Bạn cũng có thể áp dụng biểu thức chính quy để đảm bảo bạn nhận được đúng tệp, ví dụ: chỉ xử lý tệp .txt:
perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt
Để "xem trước" những gì đang xảy ra, chỉ cần thay thế backticks bằng dấu ngoặc kép và trả trước print:
perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
chmodchức năng
perl -lpe 'chmod 0755, $_' file.txt- sử dụng -lcho tính năng "tự động nhai"
Bạn cũng có thể sử dụng AWK để có thể linh hoạt hơn để xử lý tệp
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
nếu tệp của bạn có dấu phân cách trường như:
trường1, trường2, trường3
Để chỉ nhận được lĩnh vực đầu tiên bạn làm
awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt
Bạn có thể kiểm tra thêm chi tiết về Tài liệu GNU https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple
Logic áp dụng cho nhiều mục tiêu khác. Và làm thế nào để đọc .sh_history của mỗi người dùng từ / home / filesystem? Nếu có hàng ngàn người thì sao?
#!/bin/ksh
last |head -10|awk '{print $1}'|
while IFS= read -r line
do
su - "$line" -c 'tail .sh_history'
done
Đây là kịch bản https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh
xargsđã được xây dựng ban đầu để đáp ứng nhu cầu này, một số tính năng, như lệnh xây dựng càng lâu càng tốt trong môi trường hiện tại để gọichmodtrong trường hợp này càng ít càng tốt, giảm dĩa đảm bảo hiệu quả.while ;do..done <$fileimplie chạy 1 fork cho 1 file.xargscó thể chạy 1 ngã ba cho hàng ngàn tệp ... một cách đáng tin cậy.