Bagaimana saya bisa mengedit semua file yang dikembalikan oleh find in vi di Linux?

27

Sesuatu yang sering saya lakukan adalah menjalankan perintah find dan kemudian mengedit semuanya secara vi, yang terlihat seperti ini:

> find . "*.txt"
./file1.txt
./file2.txt
./path/to/file3.txt

> vi ./file1.txt ./file2.txt ./path/to/file3.txt

Apakah ada cara pintar & sederhana untuk melakukan ini semua dalam satu baris perintah?

kasar
sumber
1
Anda dapat menyalurkannya ke vi: find. "* .txt" | xargs vi
MaQleod
1
@ MAQleod: Secara teknis itu akan disalurkan ke xargs .
grawity
Perpipaan untuk xargsmenghancurkan terminal shell saya. Solusi yang tepat adalah yang di bawah ini oleh @DevSolar
typelogic

Jawaban:

41

Ini harus melakukan trik:

find . -name "*.txt" -exec vim {} + 

Gunakan Vim, lebih baik untuk kesehatan Anda. :-)

Opsi yang sering diabaikan +untuk -execmembuat semua nama file (hingga batas panjang garis) muncul dalam satu baris, yaitu Anda masih mendapatkan semua file dibuka dalam satu vim sesi (navigasikan dengan :nuntuk :Nfile berikutnya dan sebelumnya).

Dengan vim -pAnda mendapatkan tab file untuk setiap file. Periksa :help tab-page-commandslebih detail.

Dengan vim -oAnda akan mendapatkan windows split secara horizontal untuk setiap file, vim -Osecara vertikal membagi windows. Periksa :help window-move-cursorlebih detail.

Perhatikan bahwa versi sebelumnya dari jawaban ini vim $(find . -name "*.txt"),, tidak berfungsi dengan spasi di nama file, dan memiliki implikasi keamanan.

Perpipaan menjadi xargs vimemberi Warning: Input is not from a terminal, plus terminal dengan perilaku benar-benar palsu sesudahnya. Grawity pengguna menjelaskan alasannya di komentar di bawah ini, dan dengan sedikit penjelasan lebih lanjut dalam pertanyaan ini .

DevSolar
sumber
4
Tidak tahu berapa banyak yang Anda ketahui tentang vim, tetapi butuh saya / selamanya / untuk mengetahui bahwa: n menunjukkan file berikutnya dan: N menunjukkan yang sebelumnya.
zpletan
4
@DevSolar: Vim mengharapkan stdinnya sama dengan terminal pengendali, dan melakukan berbagai ioctls terkait terminal pada stdin secara langsung. (Anda dapat menganggap ini sebagai bug. Vim tentu dapat membuka /dev/ttydan memanggil ioctl () untuk itu; terlalu malas untuk melakukannya.) Ketika dipanggil oleh xargs, vim menerima /dev/nullsebagai input standar, yang hanya mengabaikan ioctls kontrol-terminal.
grawity
3
@zpletan: vim -pjika Anda ingin tab file. ( gtdan gTuntuk bernavigasi, atau klik dengan mouse Anda.)
grawity
2
FYI, untuk menghindari peringatan saat mengirim pesan vim, cukup tentukan -sebagai argumen pertama, seperti pada echo foobar | vim -.
Konrad Rudolph
2
@Konrad Rudolph: find . -name "*.txt" | vim -memberi Anda sesi vim pada file yang tidak disebutkan namanya yang berisi nama - nama file yang ditemukan, yang bukan apa yang diminta OP ...
DevSolar
4

Atau jalankan vim dan dari sana:

:args **/*.txt
Benoit
sumber
1

Selain itu, jika Anda ingin mereka membuka satu per satu, Anda juga dapat menggunakan find -exec atau menggunakan simple untuk loop. Diedit per komentar ceving.

find . -name "*.txt" -exec vi {} \;

atau

OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for i in `find . -name "*.txt"`
    do
        vi $i
    done
IFS=$OLDIFS
Serigala tua
sumber
... tetapi mengapa Anda ingin melakukan itu?
DevSolar
@DevSolar Yang pertama adalah menunjukkan kemampuan dalam menemukan, yang kedua adalah loop tujuan umum. Mungkin Anda ingin melakukan sesuatu untuk setiap file sebelum Anda mengeditnya.
OldWolf
Apakah Anda pernah mencoba yang kedua? Pertama: find mengembalikan direktori saat ini karena -nametidak ada. Dan kedua: perintah gagal total segera setelah nama file berisi spasi. -1 untuk jawaban yang keliru.
ceving
Sebenarnya, subjek spasi dalam nama file berlaku untuk jawaban saya juga. Saya bahkan tidak bisa memikirkan cara untuk menanganinya dengan baik tanpa mengubahnya dari baris perintah menjadi skrip sendiri. Ada alasan bagus mengapa spasi dalam nama file tidak disarankan.
DevSolar
@ceving Poin yang valid. Saya kira poster yang asli ternyata valid untuk kebutuhannya. Editing.
OldWolf
0

Jika Anda sudah mengetikkan findperintah, saya menemukan bahwa bisa lebih mudah digunakan xargsuntuk membuka hasil pencarian:

find . -name "*.txt" | xargs vim -p

The -ppilihan memberitahu vim untuk membuka setiap file di tab baru. Saya menemukan ini lebih nyaman daripada hanya menggunakan buffer, tetapi jika Anda tidak maka tinggalkan opsi itu.

Cory Klein
sumber
terima kasih saya terhubung untuk mencari jadi perintah saya adalah: cari nama file | xargs vim -p
talsibony
0

Untuk mengedit semua *.txt, Anda hanya dapat menjalankan: vim *.txt. Untuk mengedit file yang dikembalikan oleh find, baca lebih lanjut.


Pada Unix / macOS, Anda dapat menggunakan finddengan BSD xargs(lihat man xargs:), mis

find -L . -name "*.txt" -type f -print0 | xargs -o -0 vim

-o( xargs): Buka kembali stdin sebagai / dev / tty dalam proses anak sebelum menjalankan perintah.

Terkait: Terminal borked setelah memohon Vim dengan xargs di Vim.SE.

kenorb
sumber