Saya memiliki sekitar 10 php.ini
file di sistem saya, yang terletak di semua tempat, dan saya ingin menelusuri dengan cepat. Saya mencoba perintah ini:
locate php.ini | xargs vi
Tetapi vi
memperingatkan saya Input is not from a terminal
dan kemudian konsol mulai menjadi sangat aneh - setelah itu saya perlu menekan :q!
untuk berhenti vi
dan kemudian lepaskan dari sesi ssh dan sambungkan kembali agar konsol berperilaku normal lagi.
Saya pikir saya agak mengerti apa yang terjadi di sini - pada dasarnya perintah belum selesai ketika vi
dimulai sehingga perintah mungkin belum selesai dan vi
tidak berpikir bahwa terminal dalam mode normal.
Saya tidak tahu bagaimana cara memperbaikinya. Saya telah mencari Google dan juga unix.stackexchange.com dengan nasib buruk.
reset
untuk mereset terminal Anda ketika sedang kacau (Anda tidak harus memutuskan sambungan dari sesi ssh).Jawaban:
Catatan: ini akan memiliki masalah jika path file Anda memiliki spasi, tetapi secara fungsional setara dengan perintah Anda.
Versi berikutnya ini akan menangani spasi dengan benar tetapi sedikit lebih rumit (baris baru dalam nama file akan tetap memecahnya)
Penjelasan:
Apa yang terjadi adalah bahwa program mewarisi deskriptor file mereka dari proses yang menelurkan mereka.
xargs
memiliki STDIN yang terhubung ke STDOUTlocate
, jadivi
tidak tahu apa STDIN asli sebenarnya.sumber
xargs
untuk itu tidak dapat dilakukan secara langsung dengan shell (ataufind
). Namun saya bisa memikirkan kasus di mana itu akan menjadi solusi terbaik. Jadi, selama Anda memahami apaxargs
yang dilakukan, bagaimana ia memecah argumen, bagaimana menjalankan program, dll, dan menggunakannya dengan benar, saya akan mengatakan untuk itu :-P... | awk '{print $3}' | xargs | sed -e 's/ /+/g' | bc
(untuk menambahkan semua nilai-nilai bidang 3). atau dengansed -e 's/ /|/g'
membangun regexp. dan ya, seperti alat apa pun, Anda perlu tahu cara menggunakannya dan apa batasan dan peringatannya.vi $(...)
Pendekatan juga memiliki masalah dengan wildcard pada kulit selainzsh
.xargs
pendekatan di samping masalah spasi putih, nama file dengan tanda kutip tunggal, tanda kutip ganda dan garis miring terbalik juga merupakan masalah.Pertanyaan ini sebelumnya telah ditanyakan di forum Pengguna Super .
Mengutip dari jawaban @ grawity pada pertanyaan itu:
Ini disebutkan di halaman manual untuk xarg. Dari OSX / BSD:
Karenanya, pada OSX, Anda dapat menggunakan perintah berikut:
Sementara, tidak ada saklar langsung pada versi GNU, perintah ini akan berfungsi. (Pastikan untuk memasukkan
dummy
string, jika tidak akan menjatuhkan file pertama.)Solusi di atas adalah milik Jaime McGuigan di SuperUser . Menambahkannya di sini untuk pengunjung masa depan yang mencari situs untuk kesalahan ini.
sumber
xargs sh -c 'emacs "$@" < /dev/tty' emacs
apa yang mereka klaim sebagai alternatif yang lebih fleksibel dan portabel (meskipun agak lucu bagi GNU untuk lebih memilih portabilitas daripada fitur :).Dengan GNU
findutils
, dan sebuah shell dengan dukungan untuk substitusi proses (ksh, zsh, bash), Anda dapat melakukan:Idenya adalah untuk lulus daftar file melalui
-a filename
bukan stdin. Menggunakan-0
memastikan itu berfungsi terlepas dari apa karakter atau non-karakter nama file mungkin berisi.Dengan
zsh
, Anda bisa melakukan:(di mana
0
bendera ekspansi parameter untuk dibagi pada NUL).Namun perhatikan bahwa bertentangan dengan
xargs -r
itu masih berjalanvi
tanpa argumen jika tidak ada file yang ditemukan.sumber
Edit beberapa php.ini dalam editor yang sama?
Mencoba:
vim -o $(locate php.ini)
sumber
Kesalahan ini terjadi ketika vim dipanggil dan terhubung ke output pipa sebelumnya, bukan terminal dan menerima input yang berbeda yang tidak terduga (seperti NUL). Hal yang sama terjadi ketika Anda menjalankan :,
vim < /dev/null
jadireset
perintah dalam hal ini membantu. Ini dijelaskan dengan baik oleh grawity di superuser .Pada Unix / OSX Anda dapat menggunakan
xargs
dengan-o
parameter, seperti:Di Linux coba solusi berikut ini:
Atau gunakan GNU
parallel
alih-alihxargs
untuk memaksa alokasi tty, misalnya:Catatan:
parallel
pada Unix / OSX tidak akan berfungsi karena memiliki parameter yang berbeda dan tidak mendukung tty.Banyak perintah populer lainnya menyediakan alokasi pseudo-tty juga (seperti
-t
dalamssh
), jadi periksa bantuan.Atau gunakan
find
untuk meneruskan nama file untuk diedit, jadi tidak perluxargs
, cukup gunakan-exec
, misalnya:sumber
@ Patrick
IFS
retas hanya diperlukan untuk kerang bodoh sepertibash
danzsh
.fish
memisahkan string pada baris baru secara default.Dan Tuhan membantu kita semua jika salah satu dari kita benar-benar memiliki file dengan baris baru dalam namanya. Setelah 17 tahun menggunakan Linux, saya belum pernah melihatnya sekali pun. Saya hanya akan bersusah payah mendukung nama file dengan baris baru di dalamnya untuk skrip yang harus bekerja apa pun yang terjadi, tetapi skrip seperti itu mungkin tidak menjalankan vim secara interaktif.
sumber
zsh
memisahkan SPC, TAB, NL dan NUL secara default. Hal yang tidak dilakukan dibandingkanbash
adalah melakukan globbing pada hasilnya sehingga karakter wildcard dalam nama file tidak menjadi masalah. Dizsh
, Anda akan melakukanIFS=$'\0'; vi $(locate -0 php.ini)
atau seperti yang saya tunjukkan dalam jawaban sayavi ${(0)"$(locate -0 php.ini)"}
untuk operator pemisahan yang eksplisit. Perhatikan juga tcsh'svi "`locate php.ini`"
$ f='not there'<ret>$ ls $f<ret>
tetapi ini tidak: lsecho not there
. OK sepertinya saya perlu memperbarui ini sedikit.ls "$(echo test; echo other test)"
. Hanya ikan yang melakukan hal yang benar.$IFS
atau melalui operator eksplisit (f
dan0
flag ekspansi parameter). Untuk nama file yang sewenang-wenang, membelah dengan kata atau membelah dengan baris sama-sama salah , Anda perlu memecah pada NUL atau parsing beberapa pengkodean, yangfish
tidak bisa dilakukan. Inzsh
, ituIFS=$'\0'; ls -ld -- $(printf '%s\0' "$file1" "$file2")
atauls -ld -- ${(0)"$(printf '%s\0' "$file1" "$file2")"}
Cara cepat untuk melakukannya, dengan asumsi Anda dapat menjamin tidak ada path file berisi SPC, TAB, NL,
*
,?
,[
karakter (juga\
dan{...}
dalam beberapa kerang) adalah dengan menggunakan back-kutu (alias aksen kuburan) untuk menjalankan perintah sebelum perintah lain berjalan.Misalnya
Perintah yang terkandung dalam back-ticks akan dieksekusi terlebih dahulu. Output dari perintah yang terkandung kemudian dieksekusi oleh perintah yang dinyatakan sebelum tick-back.
Sebagai contoh, pada baris di atas,
find / -type f -name 'php.ini'
perintah akan dieksekusi terlebih dahulu, kirim output, dan kemudianvi
akan dieksekusi pada hasil split + glob yang diterapkan pada output itu.sumber
$(find ...)
saja.vi
menggunakan metode ini. Sangat mungkin bisa rusak pada baris atau spasi baru, tergantung pada bagaimanavi
membaca dan menjalankan output.