2009-07-01 8 views
1

Dernièrement, je me suis souvent retrouvé vouloir exécuter une commande sur la sortie d'une autre commande qui a une sortie sur plusieurs lignes. Par exemple, disons que j'ai une commande qui renvoie un nombre de chemins de fichier sur une nouvelle ligne et que je souhaite supprimer tous ces fichiers.Commande Shell qui parcourt les lignes?

Y at-il une commande qui peut m'aider à faire cela?

+1

Dans quel environnement? Les fenêtres? UNIX? – Joey

Répondre

6

On dirait que vous êtes à la recherche xargs. De la page man:

xargs lit des arguments de l'entrée standard, délimitées par des blancs (qui peuvent être protégés par des guillemets doubles ou simples ou une barre oblique inverse) ou des sauts de ligne, et exécute la commande (par défaut/bin/echo) une ou plusieurs fois avec des arguments initiaux suivis d'arguments lus à partir de l'entrée standard.

Vous pouvez faire des choses comme:

ls | grep -v '*.cpp' | xargs rm 

La commande ci-dessus supprimerait tout dans le répertoire courant, sauf *.cpp fichiers.

3

shells bash comme vous pouvez le faire:

rm `your command` 

ou

rm $(your command) 
+1

Cela fonctionne bien jusqu'à ce que les noms de fichiers contiennent des espaces, ou la liste se développe trop longtemps. –

3

Sous Windows, CMD:

for /f "usebackq delims=" %i in (`your command`) @del "%i" 

Powershell:

your command | Remove-Item 
0

essayer

cat file | while read i; do echo "working on line $i"; done 

Bien que vous pouvez avoir des problèmes avec des lignes ayant des espaces. Je ne me souviens jamais comment résoudre ce problème. Veuillez noter que cette commande fonctionne pour chaque manipulation ligne par ligne. Utiliser xargs ne fonctionne que pour le cas d'exemple que vous avez demandé (et des cas similaires), mais si vous pouvez résoudre votre problème avec xargs, allez-y sans hésiter.

+0

Vous recherchez une coupe. Cela imprimerait la première colonne. Si vous voulez obtenir un colombophile, consultez sed et/ou awk. http://www.manpagez.com/man/1/cut/ Fichier cat | alors que je lis; do FOO = echo $ i | coupe -f1; echo $ FOO; done (EDIT: déplacé de réponse à commentaire) – John

1
ls | xargs rm 

une utilisation intéressante (pour rechercher un répertoire pour une phrase dans un fichier)

find /path/to/dir | xargs grep "search text" 

que l'on est pas lié, mais il montre comment fonctionne xargs

1

En supposant un UNIX like environment:

Pour gérer les espaces dans les noms, utilisez l'indicateur -0 pour xargs. Avec trouvaille:

find . -name '*.mp3' -print0 | xargs -0 dosomething 

D'autres commandes ont plusieurs commutateurs pour la sortie séparés NUL, généralement -0 ou -z.Si votre liste est orientée vers la ligne, faire quelque chose comme:

cat filelist | tr -s '\012\015' '\000' | xargs -0 dosomething 

qui utilise tr pour traduire les nouvelles lignes et à linefeeds nuls, la manipulation UNIX et DOS (et même Mac Classic) ligne se termine et sauter des lignes vides. N'oubliez pas que les nouvelles lignes sont des caractères de nom de fichier valides sur la plupart des systèmes de fichiers de type UNIX.

Si dosomething est complexe, vous pouvez utiliser les fonctions de bash:

dosomething() { 
    while [ -n "$1" ] ; do 
     out="$(basename "$1" .mp3).ogg" 
     convert "$1" "converted/$out" 
     shift 
    done 
} 

export -f dosomething 

et invoquez xargs comme:

cat filelist | tr -s '\012\015' '\000' | xargs -0 bash -c 'dosomething "[email protected]"' -- 

Notez l'utilisation judicieuse des guillemets doubles pour préserver des espaces, et double- Les chaînes entre guillemets peuvent être imbriquées dans les opérateurs eval $() entre guillemets.

Au sein de la fonction, vous pouvez écrire "[email protected]" pour obtenir une liste d'arguments correctement cité pour passer à un sous-processus:

dosomething() { 
    command1 preargs "[email protected]" postargs | command2 
    command3 "[email protected]" 
} 

Vous pouvez également utiliser read travailler ligne par ligne:

cat filelist | while read i ; do something "$i" ; done 

mais xargs vous obtient tous les args à la fois.

Questions connexes