GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana saya bisa meneruskan semua argumen dengan xargs di tengah perintah di linux

Gunakan -I opsi:

echo prefix | xargs -I % echo % post

Keluaran:

prefix post

Ini adalah salah satu cara untuk melakukannya

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

atau menggunakan backtick

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

Misalnya, jika nama file adalah 100, 2, 9, 3.14, 10, 1 perintahnya adalah

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

Untuk menangani nama file dengan spasi atau karakter khusus lainnya, pertimbangkan ini diperbaiki versi luar biasa @joeytwiddle jawaban (yang tidak mengurutkan secara numerik, lihat pembahasan di bawah):

#-- 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"

Alternatif untuk xargs (khusus bash)

xargs adalah perintah eksternal, pada contoh sebelumnya memanggil sh yang pada gilirannya memanggil pdftk .

Alternatifnya adalah menggunakan mapfile bawaan jika tersedia, atau gunakan parameter posisi. Contoh berikut menggunakan dua fungsi, print0_files menghasilkan nama file yang diakhiri NUL dan create_pdf memanggil pdftk :

print0_files | create_pdf combinewd2.pdf

Fungsi didefinisikan sebagai berikut

#-- 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"
}

Diskusi

Seperti yang ditunjukkan dalam komentar, jawaban awal yang sederhana tidak berfungsi dengan nama file yang mengandung spasi atau karakter khusus lainnya. Jawaban oleh @joeytwiddle menangani karakter khusus, meskipun tidak diurutkan secara numerik

#-- 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"

Itu tidak mengurutkan secara numerik karena setiap nama file diawali dengan ./ oleh find memerintah. Beberapa versi find dukungan perintah -printf '%P\0' yang tidak menyertakan ./ awalan. Perbaikan portabel yang lebih sederhana adalah dengan menambahkan -d, --dictionary-order ke sort perintah sehingga hanya mempertimbangkan spasi kosong dan karakter alfanumerik sebagai perbandingan, tetapi mungkin masih menghasilkan urutan yang salah

#-- 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"

Jika nama file berisi desimal, ini dapat menyebabkan pengurutan numerik yang salah. sort perintah tidak memungkinkan offset ke bidang saat menyortir, sort -k1.3n , seseorang harus berhati-hati dalam menentukan pemisah bidang jika nama file dibuat seumum mungkin, untungnya sort -t '\0' menentukan NUL sebagai pemisah bidang, dan find -print0 opsi menunjukkan NUL digunakan sebagai pembatas antara nama file, jadi sort -z -t '\0' menentukan NUL sebagai pembatas catatan dan pemisah bidang-- setiap nama file kemudian menjadi catatan bidang tunggal. Mengingat hal itu, kita kemudian dapat mengimbangi ke dalam bidang tunggal dan melewati ./ awalan dengan menentukan karakter ke-3 dari bidang ke-1 sebagai posisi awal untuk pengurutan numerik, sort -k1.3n -z -t '\0' .


Ini harus bekerja pada nama file yang berisi spasi, baris baru, apostrof, dan tanda kutip (semuanya dimungkinkan pada sistem file UNIX):

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

Itu mungkin berlebihan dibandingkan dengan jawaban yang diterima, jika Anda tahu Anda bekerja dengan nama file sederhana.

Namun jika Anda menulis skrip yang akan digunakan lagi di masa mendatang, diharapkan skrip tersebut tidak akan meledak suatu hari saat bertemu dengan masukan yang tidak biasa (namun valid).

Ini pada dasarnya adalah adaptasi dari jawaban andrewdotn yang menghentikan file input dengan byte nol, bukan dengan baris baru, sehingga mempertahankan nama file yang berisi satu atau lebih karakter baris baru.

Opsi masing-masing -print0 , -z dan -0 beri tahu setiap program bahwa input/output harus dibatasi oleh byte nol. Tiga program berbeda, tiga argumen berbeda!


Jelek, tapi Anda bisa menjalankan sh -c dan akses daftar argumen yang diteruskan oleh xargs sebagai "${@}" , seperti ini:

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

"${0}" ekstra pada akhirnya ada karena, sebagai sh kata halaman manual

-c tali

Jika -c ada opsi, maka perintah dibaca dari string . Jika ada argumen setelah string , mereka ditetapkan ke parameter posisi, dimulai dengan $0 .

Untuk mengujinya, pertama mari kita buat beberapa file dengan nama rumit yang akan mengacaukan sebagian besar solusi lain:

$ 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

Semua argumen dikutip dengan benar. Perhatikan bahwa ini akan gagal jika ada nama file yang berisi baris baru, dan ls -v itu pada dasarnya adalah ls | sort -n .


Linux
  1. Bagaimana saya bisa menjalankan perintah yang berbeda tetapi dengan argumen yang sama?

  2. Bagaimana saya bisa mendaftar semua pengguna yang terkunci di Linux?

  3. Bagaimana saya bisa memindahkan file dengan xargs di Linux?

  1. Urutkan Perintah di Linux dengan Contoh

  2. Cara Melewati Kata Sandi ke Perintah SCP di Linux

  3. Cara meneruskan output perintah sebagai beberapa argumen ke perintah lain

  1. Perintah sortir Linux dengan Contoh

  2. Cara Menggunakan Perintah IP di Linux dengan Contoh

  3. Perintah DD Linux - 15 Contoh dengan Semua Opsi