GNU/Linux >> Tutoriels Linux >  >> Linux

Comment puis-je passer tous les arguments avec xargs au milieu de la commande sous Linux

Utilisez -I choix :

echo prefix | xargs -I % echo % post

Sortie :

prefix post

C'est une façon de faire

pdftk $(ls | sort -n) cat output combinewd2.pdf

ou en utilisant le backtick

pdftk `ls | sort -n` cat output combinewd2.pdf

Par exemple, si les noms de fichiers sont 100, 2, 9, 3.14, 10, 1, la commande sera

pdftk 1 2 3.14 9 10 100 cat output combinewd2.pdf

Pour gérer les noms de fichiers avec des espaces ou d'autres caractères spéciaux, considérez ceci comme fixe version de l'excellent de @joeytwiddle réponse (qui ne trie pas numériquement, voir la discussion ci-dessous) :

#-- The following will handle special characters, and
#   will sort filenames numerically
#   e.g. filenames 100, 2, 9, 3.14, 10, 1 results in 
#      ./1 ./2 ./3.14 ./9 ./10 ./100
#
find . -maxdepth 1 -type f -print0 |
  sort -k1.3n -z -t '\0' |
  xargs -0 sh -c 'pdftk "[email protected]" cat output combinewd2.pdf' "$0"

Alternatives à xargs (spécifique à bash)

xargs est une commande externe, dans l'exemple précédent elle invoque sh qui à son tour invoque pdftk .

Une alternative consiste à utiliser le mapfile intégré s'ils sont disponibles, ou utilisez les paramètres de position. Les exemples suivants utilisent deux fonctions, print0_files génère les noms de fichiers terminés par NUL et create_pdf invoque pdftk :

print0_files | create_pdf combinewd2.pdf

Les fonctions sont définies comme suit

#-- Generate the NUL terminated filenames, numerically sorted
print0_files() {
    find . -maxdepth 1 -type f -print0 |
        sort -k1.3n -z -t '\0'
}
#-- Read NUL terminated filenames using mapfile
create_pdf() {
    mapfile -d ''
    pdftk "${MAPFILE[@]}" cat output "$1"
}
#-- Alternative using positional parameters
create_pdf() {
    local -r pdf=$1
    set --
    while IFS= read -r -d '' f; do set -- "[email protected]" "$f"; done
    pdftk "[email protected]" cat output "$pdf"
}

Discussion

Comme indiqué dans les commentaires, la réponse initiale simple ne fonctionne pas avec les noms de fichiers contenant des espaces ou d'autres caractères spéciaux. La réponse de @joeytwiddle gère les caractères spéciaux, bien qu'elle ne trie pas numériquement

#-- The following will not sort numerically due to ./ prefix,
#   e.g. filenames 100, 2, 9, 3.14, 10, 1 results in 
#      ./1 ./10 ./100 ./2 ./3.14 ./9
#
find . -maxdepth 1 -type f -print0 |
  sort -zn |
  xargs -0 sh -c 'pdftk "[email protected]" cat output combinewd2.pdf' "$0"

Il ne trie pas numériquement car chaque nom de fichier est préfixé par ./ par le find commande. Certaines versions du find prise en charge des commandes -printf '%P\0' qui n'inclurait pas le ./ préfixe. Une solution plus simple et portable consiste à ajouter le -d, --dictionary-order option au sort afin qu'elle ne considère que les espaces vides et les caractères alphanumériques dans les comparaisons, mais qu'elle produise toujours le mauvais ordre

#-- The following will not sort numerically due to decimals
#   e.g. filenames 100, 2, 9, 3.14, 10, 1 results in 
#      ./1 ./2 ./9 ./10 ./100 ./3.14
#
find . -maxdepth 1 -type f -print0 |
  sort -dzn |
  xargs -0 sh -c 'pdftk "[email protected]" cat output combinewd2.pdf' "$0"

Si les noms de fichiers contiennent des décimales, cela peut entraîner un tri numérique incorrect. Le sort la commande autorise un décalage dans un champ lors du tri, sort -k1.3n , il faut être prudent dans la définition du séparateur de champs si les noms de fichiers doivent être aussi généraux que possible, heureusement sort -t '\0' spécifie NUL comme séparateur de champs et le find -print0 l'option indique que NUL doit être utilisé comme délimiteur entre les noms de fichiers, donc sort -z -t '\0' spécifie NUL comme délimiteur d'enregistrement et séparateur de champ - chaque nom de fichier est alors un enregistrement de champ unique. Compte tenu de cela, nous pouvons alors décaler dans le champ unique et ignorer le ./ préfixe en spécifiant le 3ème caractère du 1er champ comme position de départ pour le tri numérique, sort -k1.3n -z -t '\0' .


Cela devrait fonctionner sur les noms de fichiers contenant des espaces, des retours à la ligne, des apostrophes et des guillemets (qui sont tous possibles sur les systèmes de fichiers UNIX) :

find . -maxdepth 1 -type f -print0 |
  sort -zn |
  xargs -0 sh -c 'pdftk "[email protected]" cat output combinewd2.pdf' "$0"

Cela pourrait être exagéré par rapport à la réponse acceptée, si vous savez que vous travaillez avec des noms de fichiers simples.

Mais si vous écrivez un script qui sera réutilisé à l'avenir, il est souhaitable qu'il n'explose pas un jour lorsqu'il rencontre des entrées inhabituelles (mais valides).

Il s'agit essentiellement d'une adaptation de la réponse d'andrewdotn qui termine les fichiers d'entrée avec un octet zéro, au lieu d'un retour à la ligne, préservant ainsi les noms de fichiers contenant un ou plusieurs caractères de retour à la ligne.

Les options respectives -print0 , -z et -0 dire à chacun des programmes que l'entrée/sortie doit être délimitée par l'octet zéro. Trois programmes différents, trois arguments différents !


C'est moche, mais vous pouvez exécuter sh -c et accéder à la liste des arguments passés par xargs comme "${@}" , comme ceci :

ls | sort -n | xargs -d'\n' sh -c 'pdftk "${@}" cat output combinewd2.pdf' "${0}"

Les "${0}" supplémentaires à la fin est là car, comme le sh la page de manuel indique

-c chaîne

Si le -c l'option est présente, alors les commandes sont lues à partir de string . S'il y a des arguments après la chaîne , ils sont affectés aux paramètres de position, en commençant par $0 .

Pour tester cela, créons d'abord des fichiers avec des noms compliqués qui gâcheront la plupart des autres solutions :

$ seq 1 100 | xargs -I{} touch '{} with "spaces"'
$ ls
1 with "spaces"    31 with "spaces"  54 with "spaces"  77 with "spaces"
10 with "spaces"   32 with "spaces"  55 with "spaces"  78 with "spaces"
100 with "spaces"  33 with "spaces"  56 with "spaces"  79 with "spaces"
11 with "spaces"   34 with "spaces"  57 with "spaces"  8 with "spaces"
12 with "spaces"   35 with "spaces"  58 with "spaces"  80 with "spaces"
13 with "spaces"   36 with "spaces"  59 with "spaces"  81 with "spaces"
14 with "spaces"   37 with "spaces"  6 with "spaces"   82 with "spaces"
15 with "spaces"   38 with "spaces"  60 with "spaces"  83 with "spaces"
16 with "spaces"   39 with "spaces"  61 with "spaces"  84 with "spaces"
17 with "spaces"   4 with "spaces"   62 with "spaces"  85 with "spaces"
18 with "spaces"   40 with "spaces"  63 with "spaces"  86 with "spaces"
19 with "spaces"   41 with "spaces"  64 with "spaces"  87 with "spaces"
2 with "spaces"    42 with "spaces"  65 with "spaces"  88 with "spaces"
20 with "spaces"   43 with "spaces"  66 with "spaces"  89 with "spaces"
21 with "spaces"   44 with "spaces"  67 with "spaces"  9 with "spaces"
22 with "spaces"   45 with "spaces"  68 with "spaces"  90 with "spaces"
23 with "spaces"   46 with "spaces"  69 with "spaces"  91 with "spaces"
24 with "spaces"   47 with "spaces"  7 with "spaces"   92 with "spaces"
25 with "spaces"   48 with "spaces"  70 with "spaces"  93 with "spaces"
26 with "spaces"   49 with "spaces"  71 with "spaces"  94 with "spaces"
27 with "spaces"   5 with "spaces"   72 with "spaces"  95 with "spaces"
28 with "spaces"   50 with "spaces"  73 with "spaces"  96 with "spaces"
29 with "spaces"   51 with "spaces"  74 with "spaces"  97 with "spaces"
3 with "spaces"    52 with "spaces"  75 with "spaces"  98 with "spaces"
30 with "spaces"   53 with "spaces"  76 with "spaces"  99 with "spaces"
$  ls | sort -n | xargs -d'\n' sh -c 'set -x; pdftk "${@}" cat output combinewd2.pdf' "${0}"
+ pdftk '1 with "spaces"' '2 with "spaces"' '3 with "spaces"' '4 with "spaces"' '5 with "spaces"' '6 with "spaces"' '7 with "spaces"' '8 with "spaces"' '9 with "spaces"' '10 with "spaces"' '11 with "spaces"' '12 with "spaces"' '13 with "spaces"' '14 with "spaces"' '15 with "spaces"' '16 with "spaces"' '17 with "spaces"' '18 with "spaces"' '19 with "spaces"' '20 with "spaces"' '21 with "spaces"' '22 with "spaces"' '23 with "spaces"' '24 with "spaces"' '25 with "spaces"' '26 with "spaces"' '27 with "spaces"' '28 with "spaces"' '29 with "spaces"' '30 with "spaces"' '31 with "spaces"' '32 with "spaces"' '33 with "spaces"' '34 with "spaces"' '35 with "spaces"' '36 with "spaces"' '37 with "spaces"' '38 with "spaces"' '39 with "spaces"' '40 with "spaces"' '41 with "spaces"' '42 with "spaces"' '43 with "spaces"' '44 with "spaces"' '45 with "spaces"' '46 with "spaces"' '47 with "spaces"' '48 with "spaces"' '49 with "spaces"' '50 with "spaces"' '51 with "spaces"' '52 with "spaces"' '53 with "spaces"' '54 with "spaces"' '55 with "spaces"' '56 with "spaces"' '57 with "spaces"' '58 with "spaces"' '59 with "spaces"' '60 with "spaces"' '61 with "spaces"' '62 with "spaces"' '63 with "spaces"' '64 with "spaces"' '65 with "spaces"' '66 with "spaces"' '67 with "spaces"' '68 with "spaces"' '69 with "spaces"' '70 with "spaces"' '71 with "spaces"' '72 with "spaces"' '73 with "spaces"' '74 with "spaces"' '75 with "spaces"' '76 with "spaces"' '77 with "spaces"' '78 with "spaces"' '79 with "spaces"' '80 with "spaces"' '81 with "spaces"' '82 with "spaces"' '83 with "spaces"' '84 with "spaces"' '85 with "spaces"' '86 with "spaces"' '87 with "spaces"' '88 with "spaces"' '89 with "spaces"' '90 with "spaces"' '91 with "spaces"' '92 with "spaces"' '93 with "spaces"' '94 with "spaces"' '95 with "spaces"' '96 with "spaces"' '97 with "spaces"' '98 with "spaces"' '99 with "spaces"' '100 with "spaces"' cat output combinewd2.pdf

Tous les arguments sont cités correctement. Notez que cela échouera si des noms de fichiers contiennent des retours à la ligne, et que ls -v est essentiellement ls | sort -n .


Linux
  1. Commande Linux DD - 15 exemples avec toutes les options

  2. Commande de tri sous Linux avec des exemples

  3. Comment transmettre un mot de passe à la commande SCP sous Linux

  4. Comment puis-je répertorier tous les utilisateurs verrouillés sous Linux ?

  5. Comment passer la sortie de la commande sous forme de plusieurs arguments à une autre commande

Comment configurer le réseau IP avec la commande nmcli sous Linux

Comment utiliser la commande Linux rm avec des exemples

Comment gérer les mots de passe Linux avec la commande pass

Comment transmettre un mot de passe à la commande SSH sous Linux

Comment utiliser la puissante commande Xargs sous Linux [expliqué avec des exemples]

Comment utiliser la commande xargs sous Linux ?