Jak uruchomić polecenie dla każdej linii pliku?

Na przykład, w tej chwili używam następujących plików, aby zmienić kilka ścieżek uniksowych, które napisałem do pliku:

cat file.txt | while read in; do chmod 755 "$in"; done
Czy istnieje bardziej elegancki i bezpieczniejszy sposób?
Author: Bonifacio2, 2012-12-18

8 answers

Jeśli Twój plik nie jest zbyt duży i wszystkie pliki mają dobrze nazwane (bez spacji lub innych znaków specjalnych, takich jak cudzysłowy), możesz po prostu:

chmod 755 $(<file.txt)

Jeśli masz znaki specjalne i / lub wiele linii w file.txt.

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

Jeśli Twoje polecenie musi być uruchomione dokładnie 1 raz przez wpis:

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

Nie jest to potrzebne dla tej próbki, ponieważ chmod akceptuje wiele plików jako argument, ale to pasuje do tytułu pytania.

W jakimś szczególnym przypadku, można nawet zdefiniować lokalizacja argumentu pliku w poleceniach generowanych przez xargs:

xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
 73
Author: F. Hauri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-10 07:32:24

Tak.

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

W ten sposób można uniknąć cat procesu.

cat jest prawie zawsze złe dla takiego celu jak ten. Możesz przeczytać więcej o bezużyteczne użycie Cat.

 107
Author: P.P.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-08 11:10:46

Jeśli wiesz, że nie masz żadnych białych znaków na wejściu:

xargs chmod 755 < file.txt

Jeśli w ścieżkach mogą być białe spacje i jeśli masz GNU xargs:

tr '\n' '\0' < file.txt | xargs -0 chmod 755
 12
Author: glenn jackman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 23:54:35

Jeśli masz ładny selektor (na przykład all .pliki txt w katalogu) można zrobić:

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

Bash for loop

Lub twój wariant:

while read line; do chmod 755 "$line"; done <file.txt
 10
Author: d.raev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 18:49:03

Jeśli chcesz uruchomić polecenie równolegle dla każdej linii możesz użyć GNU Parallel

parallel -a <your file> <program>

Każda linia Twojego pliku zostanie przekazana do programu jako argument. Domyślnie parallel uruchamia tyle wątków, ile liczą Twoje Procesory. Ale można go określić za pomocą -j

 10
Author: janisz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-21 18:02:10

Widzę, że otagowałeś Basha, ale Perl też byłby dobrym sposobem na to:

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

Możesz również zastosować Wyrażenie regularne, aby upewnić się, że otrzymujesz odpowiednie pliki, np. tylko przetwarzać .pliki txt:

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

Aby wyświetlić podgląd tego, co się dzieje, wystarczy zastąpić backticki podwójnymi cudzysłowami i dodać print:

perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
 2
Author: 1.618,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 18:49:37

Możesz również użyć AWK, który może dać ci większą elastyczność obsługi pliku

awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt

Jeśli plik ma separator pól w postaci:

Field1, field2, field3

Aby uzyskać tylko pierwsze pole, które wykonasz

awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt

Możesz sprawdzić więcej szczegółów na temat dokumentacji GNU https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple

 0
Author: brunocrt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-11 19:01:29

Logika odnosi się do wielu innych celów. A jak odczytać .sh_history każdego użytkownika z /home / filesystem? A jeśli jest ich tysiące?

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

Oto skrypt https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh

 0
Author: igor.monteiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-30 16:41:28