Je voudrais courir:
./a.out < x.dat > x.ans
pour chaque * .dat fichier dans le répertoire A .
Bien sûr, cela pourrait être fait par bash / python / quel que soit le script, mais j'aime écrire un one-liner sexy. Tout ce que je pouvais atteindre est (toujours sans stdout):
ls A/*.dat | xargs -I file -a file ./a.out
Mais -a dans xargs ne comprend pas le 'fichier' replace-str.
Merci pour l'aide.
io-redirection
xargs
Nikolay Vyahhi
la source
la source
Réponses:
Tout d'abord, n'utilisez pas la
ls
sortie comme liste de fichiers . Utilisez l'extension shell oufind
. Voir ci-dessous pour les conséquences potentielles d'une mauvaise utilisation de ls + xargs et un exemple d'xargs
utilisation appropriée .1. Manière simple: pour la boucle
Si vous souhaitez traiter uniquement les fichiers ci-dessous
A/
, une simplefor
boucle devrait suffire:2. pre1 Pourquoi pas
ls | xargs
?Voici un exemple de la façon dont les choses peuvent mal tourner si vous utilisez
ls
avecxargs
pour le travail. Considérez un scénario suivant:commençons par créer des fichiers vides:
voir les fichiers et qu'ils ne contiennent rien:
exécutez une commande magique en utilisant
xargs
:le résultat:
Vous venez donc de remplacer les deux
mypreciousfile.dat
etmypreciousfile.dat.ans
. S'il y avait du contenu dans ces fichiers, il aurait été effacé.2. Utilisation
xargs
: la bonne façon avecfind
Si vous souhaitez insister sur l'utilisation
xargs
, utilisez-0
(noms à terminaison nulle):Remarquez deux choses:
.dat.ans
fin;"
).Les deux problèmes peuvent être résolus par différentes méthodes d'appel du shell:
3. Tout est fait en dedans
find ... -exec
Encore une fois, cela produit des
.dat.ans
fichiers et se cassera si les noms de fichiers contiennent"
. Pour ce faire, utilisezbash
et modifiez la façon dont elle est invoquée:la source
zsh
est utilisé comme shell (et SH_WORD_SPLIT n'est pas défini), tous les cas spéciaux désagréables (espaces blancs, "dans le nom de fichier, etc.) ne doivent pas être pris en compte. Le trivialfor file in A/*.dat; do ./a.out < $file > ${file%.dat}.ans ; done
fonctionne dans tous les cas.find
.Essayez de faire quelque chose comme ça (la syntaxe peut varier un peu selon le shell que vous utilisez):
$ for i in $(find A/ -name \*.dat); do ./a.out < ${i} > ${i%.dat}.ans; done
la source
somefile.dat.dat
et de rediriger toutes les sorties vers un seul fichier.somefile.dat.ans
des trucs de sortie n'auraient pas l'air si bien.-type file
serait bien (impossible< directory
), et cela rend triste la fée du nom de fichier inhabituel.Pour les modèles simples, la boucle for est appropriée:
Pour les cas plus complexes où vous avez besoin d'un autre utilitaire pour répertorier les fichiers (zsh ou bash 4 ont des modèles assez puissants que vous avez rarement besoin de trouver, mais si vous voulez rester dans le shell POSIX ou utiliser un shell rapide comme un tiret, vous aurez besoin de trouver pour tout non triviale), tandis que la lecture est la plus appropriée:
Cela gérera les espaces, car la lecture est (par défaut) orientée ligne. Il ne gérera pas les sauts de ligne et ne gérera pas les barres obliques inverses, car par défaut, il interprète les séquences d'échappement (qui vous permet en fait de passer un saut de ligne, mais find ne peut pas générer ce format). De nombreux shells ont l'
-0
option de lire, donc dans ceux-ci, vous pouvez gérer tous les caractères, mais malheureusement ce n'est pas POSIX.la source
Utilisez GNU Parallel:
Bonus supplémentaire: vous obtenez le traitement en parallèle.
Regardez les vidéos d'introduction pour en savoir plus: http://www.youtube.com/watch?v=OpaiGYxkSuQ
la source
Je pense que vous avez besoin d'au moins une invocation de shell dans les xargs:
Edit: Il convient de noter que cette approche ne fonctionne pas lorsque les noms de fichiers contiennent des espaces. Je ne peux pas travailler. Même si vous avez utilisé find -0 et xargs -0 pour que les xargs comprennent correctement les espaces, l'appel de shell -c les croasserait. Cependant, l'OP a explicitement demandé une solution xargs, et c'est la meilleure solution xargs que j'ai trouvée. Si les espaces dans les noms de fichiers peuvent poser problème, utilisez find -exec ou une boucle shell.
la source
ls
sortie .ls
génère des choses comme des espaces sans s'échapper et c'est le problème.ls
n'est pas bonne. Maisxargs
peut être utilisé en toute sécurité avec find - voir la suggestion n ° 2 dans ma réponse.Inutile de compliquer les choses. Vous pouvez le faire avec une
for
boucle:le
${file%.dat}.ans
bit supprimera le.dat
suffixe du nom de fichier du nom de fichier$file
et l'ajoutera.ans
à la fin.la source