Par exemple, pour le moment, j'utilise ce qui suit pour modifier quelques fichiers dont les chemins Unix ont été écrits dans un fichier:
cat file.txt | while read in; do chmod 755 "$in"; done
Y a-t-il un moyen plus élégant et plus sûr?
Si votre fichier n'est pas trop gros et que tous les fichiers sont bien nommés (sans espaces ni autres caractères spéciaux comme des guillemets), vous pourriez simplement:
chmod 755 $(<file.txt)
Si vous avez des caractères spéciaux et/ou beaucoup de lignes dans file.txt
.
xargs -0 chmod 755 < <(tr \\n \\0 <file.txt)
si votre commande doit être exécutée exactement 1 fois par entrée:
xargs -0 -n 1 chmod 755 < <(tr \\n \\0 <file.txt)
Ceci n'est pas nécessaire pour cet exemple, car chmod
accepte plusieurs fichiers en tant qu'argument, mais cela correspond au titre de la question.
Dans certains cas particuliers, vous pouvez même définir l'emplacement de l'argument de fichier dans les commandes générées par xargs
:
xargs -0 -I '{}' -n 1 myWrapper -arg1 -file='{}' wrapCmd < <(tr \\n \\0 <file.txt)
Oui.
while read in; do chmod 755 "$in"; done < file.txt
De cette façon, vous pouvez éviter un processus cat
.
cat
est presque toujours mauvais pour un objectif comme celui-ci. Vous pouvez en savoir plus sur Utilisation inutile de Cat.
Si vous savez que vous n'avez aucun espace dans l'entrée:
xargs chmod 755 < file.txt
S'il peut y avoir des espaces dans les chemins et si vous avez GNU xargs:
tr '\n' '\0' < file.txt | xargs -0 chmod 755
si vous avez un sélecteur Nice (par exemple tous les fichiers .txt dans un répertoire), vous pouvez faire:
for i in *.txt; do chmod 755 "$i"; done
ou une variante de votre part:
while read line; do chmod 755 "$line"; done <file.txt
Si vous voulez exécuter votre commande en parallèle pour chaque ligne, vous pouvez utiliser GNU Parallel
parallel -a <your file> <program>
Chaque ligne de votre fichier sera transmise au programme en tant qu’argument. Par défaut, parallel
exécute autant de threads que votre CPU compte. Mais vous pouvez le spécifier avec -j
Je vois que vous avez marqué bash, mais Perl serait aussi un bon moyen de faire ceci:
Perl -p -e '`chmod 755 $_`' file.txt
Vous pouvez également appliquer une expression régulière pour vous assurer d'obtenir les bons fichiers, par exemple. traiter uniquement les fichiers .txt:
Perl -p -e 'if(/\.txt$/) `chmod 755 $_`' file.txt
Pour "prévisualiser" ce qui se passe, remplacez simplement les guillemets par des guillemets et ajoutez le préfixe print
:
Perl -p -e 'if(/\.txt$/) print "chmod 755 $_"' file.txt
Vous pouvez également utiliser AWK, ce qui peut vous donner plus de flexibilité pour gérer le fichier.
awk '{ print "chmod 755 "$0"" | "/bin/sh"}' file.txt
si votre fichier a un séparateur de champ comme:
champ1, champ2, champ3
Pour obtenir uniquement le premier champ que vous faites
awk -F, '{ print "chmod 755 "$1"" | "/bin/sh"}' file.txt
Vous pouvez vérifier plus de détails sur GNU Documentation https://www.gnu.org/software/gawk/manual/html_node/Very-Simple.html#Very-Simple
La logique s'applique à de nombreux autres objectifs. Et comment lire .sh_history de chaque utilisateur à partir de/home/système de fichiers? Et s'il y en avait des milliers?
#!/bin/ksh
last |head -10|awk '{print $1}'|
while IFS= read -r line
do
su - "$line" -c 'tail .sh_history'
done
Voici le script https://github.com/imvieira/SysAdmin_DevOps_Scripts/blob/master/get_and_run.sh