Làm cách nào tôi có thể chỉnh sửa tất cả các tệp được trả về bằng vi trong Linux?


27

Một cái gì đó tôi thấy mình đang làm rất nhiều là chạy một lệnh find và sau đó chỉnh sửa tất cả chúng trong vi, trông giống như thế này:

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

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

Có một cách thông minh & đơn giản để làm tất cả điều này trong một dòng lệnh?


1
Bạn có thể ống nó vào vi: tìm. "* .Txt" | xargs vi
MaQleod

1
@MaQleod: Về mặt kỹ thuật, nó sẽ là đường ống đến xargs .
grawity


Đường ống để xargsphá hủy thiết bị đầu cuối vỏ của tôi. Giải pháp phù hợp là giải pháp dưới đây của @DevSolar
typelogic

Câu trả lời:


41

Cái này cần phải dùng mẹo:

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

Sử dụng Vim, nó tốt hơn cho sức khỏe của bạn. :-)

+Tùy chọn bỏ qua để -execlàm cho tất cả tên tệp (giới hạn độ dài tối đa của dòng) xuất hiện trong một dòng, tức là bạn vẫn nhận được tất cả các tệp được mở trong một vim phiên (được điều hướng cho tệp :ntiếp theo và :Ncho tệp trước đó).

Với vim -pbạn có được một tab tập tin cho mỗi tập tin. Kiểm tra :help tab-page-commandsđể biết thêm chi tiết.

Với vim -obạn sẽ có được các cửa sổ phân chia theo chiều ngang cho mỗi tệp, các vim -Ocửa sổ phân chia theo chiều dọc. Kiểm tra :help window-move-cursorđể biết thêm chi tiết.

Lưu ý rằng phiên bản trước của câu trả lời này vim $(find . -name "*.txt"), không hoạt động với khoảng trắng trong tên tệp và có ý nghĩa bảo mật.

Đường ống vào xargs vicho một Warning: Input is not from a terminal, cộng với một thiết bị đầu cuối với hành vi hoàn toàn không có thật sau đó. Sự khéo léo của người dùng đã giải thích lý do tại sao trong một bình luận dưới đây, và với một chút giải thích hơn trong câu hỏi này .


4
Không biết bạn biết bao nhiêu về vim, nhưng tôi đã mất / mãi mãi / để tìm ra rằng: n hiển thị tệp tiếp theo và: N hiển thị tệp trước đó.
zpletan

4
@DevSolar: Vim hy vọng stdin của nó giống với thiết bị đầu cuối điều khiển của nó và thực hiện trực tiếp các ioctls khác nhau liên quan đến thiết bị đầu cuối trên stdin. (Bạn có thể coi đây là một lỗi Vim chắc chắn. Có thể mở /dev/ttyvà gọi ioctl () trên đó;. Nó chỉ là quá lười biếng để làm điều đó) Khi gọi bởi xargs, vim nhận /dev/nullnhư là đầu vào tiêu chuẩn của nó, mà chỉ cần bỏ qua IOCTLs thiết bị đầu cuối kiểm soát.
grawity

3
@zpletan: vim -pnếu bạn muốn tab tệp. ( gtgTđể điều hướng hoặc nhấp bằng chuột.)
grawity

2
FYI, để tránh cảnh báo khi dẫn vào vim, chỉ cần xác định -là đối số đầu tiên, như trong echo foobar | vim -.
Konrad Rudolph

2
@Konrad Rudolph: find . -name "*.txt" | vim -cung cấp cho bạn một phiên vim trên một tệp không tên có chứa tên của các tệp được tìm thấy, đó không phải là những gì OP yêu cầu ...
DevSolar


1

Ngoài ra, nếu bạn muốn chúng mở từng cái một, bạn cũng có thể sử dụng find -exec hoặc sử dụng một vòng lặp đơn giản. Đã chỉnh sửa theo nhận xét của ceving.

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

hoặc là

OLDIFS=$IFS
IFS=$(echo -en "\n\b")
for i in `find . -name "*.txt"`
    do
        vi $i
    done
IFS=$OLDIFS

... nhưng tại sao bạn lại muốn làm điều đó?
DevSolar

@DevSolar Đầu tiên là chỉ ra khả năng tìm kiếm, thứ hai là một vòng lặp mục đích chung. Có lẽ bạn muốn làm một cái gì đó cho mọi tập tin trước khi bạn chỉnh sửa nó.
OldWolf

Bạn đã bao giờ thử lần thứ hai chưa? Đầu tiên: find trả về thư mục hiện tại vì -namebị thiếu. Và thứ hai: lệnh thất bại thảm hại ngay khi tên tệp chứa một khoảng trắng. -1 cho câu trả lời không đúng.
ceving

Trên thực tế, chủ đề của khoảng trắng trong tên tệp cũng áp dụng cho câu trả lời của tôi. Tôi thậm chí không thể nghĩ ra cách xử lý chúng đúng cách mà không biến nó từ một dòng lệnh thành một tập lệnh nhỏ của riêng nó. Có một lý do chính đáng tại sao không gian trong tên tập tin được khuyến khích.
DevSolar

@ceving Một điểm hợp lệ. Tôi cho rằng các áp phích ban đầu tìm thấy là hợp lệ cho nhu cầu của mình. Chỉnh sửa.
OldWolf

0

Nếu bạn đã gõ findlệnh của mình, tôi thấy rằng việc sử dụng xargsđể mở kết quả tìm kiếm có thể dễ dàng hơn nhiều :

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

Các -ptùy chọn cho vim mở từng tập tin trong một tab mới. Tôi thấy điều này thuận tiện hơn là chỉ sử dụng bộ đệm, nhưng nếu bạn không bỏ qua tùy chọn đó.


cảm ơn bạn Tôi đã kết nối nó để xác định vị trí để lệnh của tôi là: xác định tên tệp | xargs vim -p
talsibony

0

Để chỉnh sửa tất cả *.txt, bạn chỉ có thể chạy : vim *.txt. Để chỉnh sửa các tập tin được trả về bởi find, đọc thêm.


Trên Unix / macOS, bạn có thể sử dụng findvới BSD xargs(xem man xargs:), vd

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

-o( xargs): Mở lại stdin dưới dạng / dev / tty trong tiến trình con trước khi thực hiện lệnh.

Liên quan: Terminal borked sau khi gọi Vim bằng xargs tại Vim.SE.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.