Ответы:
Это потому, что есть не только 1 ответ ...
shell расширение командной строкиxargs специальный инструментwhile read с некоторыми замечаниямиwhile read -uиспользование выделенного 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 и варианты.По предложению ОП cat file.txt | while read in; do chmod 755 "$in"; doneработать будет, но есть 2 вопроса:
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/
Примечание: я оставил зачеркнутую версию, потому что этот синтаксис может быть полезен при выполнении многих операций ввода-вывода с процессом Parallels:
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]примерно на 50% быстрее, чем метод, который вы описали.
Да.
while read in; do chmod 755 "$in"; done < file.txt
Таким образом, вы можете избежать catпроцесса.
catпочти всегда плохо для такой цели, как эта. Вы можете прочитать больше о Бесполезном Использовании Кошки.
cat хорошая идея, но в этом случае, указанная командаxargs
chmod(то есть действительно выполнить одну команду для каждой строки в файле).
read -rчитает одну строку из стандартного ввода ( readбез -rинтерпретации обратной косой черты, вы этого не хотите)».
если у вас есть хороший селектор (например, все .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это надежно . Этот инструмент очень старый и его код сильно пересмотрен . Его целью было изначально построить линии с учетом ограничений оболочки (64kchar / line или что-то в этом роде). Теперь этот инструмент может работать с очень большими файлами и может значительно уменьшить количество разветвлений до финальной команды. Смотрите мой ответ и / или man xargs.
brew install findutils), а затем gxargsвместо этого вызывать GNU xargs , напримерgxargs chmod 755 < file.txt
Если вы хотите запустить свою команду параллельно для каждой строки, вы можете использовать GNU Parallel
parallel -a <your file> <program>
Каждая строка вашего файла будет передана программе в качестве аргумента. По умолчанию parallelвыполняется столько потоков, сколько подсчитано для ваших процессоров. Но вы можете указать это с-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для функции "авто-chomp"
Вы также можете использовать AWK, что даст вам больше возможностей для обработки файла.
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
если в вашем файле есть разделитель полей, например:
field1, field2, field3
Чтобы получить только первое поле, которое вы делаете
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
Логика относится ко многим другим целям. А как читать .sh_history каждого пользователя из / home / filesystem? Что делать, если их тысячи?
#!/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
Я знаю, что уже поздно, но все же
Если по какой-либо причине вы столкнетесь с сохраненным в Windows текстовым файлом \r\nвместо \n, вы можете запутаться в результате, если в качестве аргумента в вашей команде указан sth после строки чтения. Так что удалите \r, например:
cat file | tr -d '\r' | xargs -L 1 -i echo do_sth_with_{}_as_line
xargsбыло initialy билд для ответа на этот вид потребности, некоторые функции, такие как команды построения как можно дольше в текущих условиях для вызоваchmodв этом случае как можно меньше, уменьшая вилки обеспечивают Efficience.while ;do..done <$fileподразумевается запуск 1 форка на 1 файл.xargsмог запустить 1 форк для тысячи файлов ... надежным способом.