Как мне отредактировать все файлы, возвращенные функцией find в vi в Linux?


27

Я часто делаю что-то, выполняя команду find, а затем редактирую их все в vi, что выглядит примерно так:

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

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

Есть ли умный и простой способ сделать все это в одной командной строке?


1
Вы можете передать это в vi: find. "* .txt" | xargs vi
MaQleod

1
@MaQleod: Технически это было бы трубкой к xargs .
благодарность


Трубопровод xargsразрушил мою оболочку терминала. Правильное решение - нижеприведенное @DevSolar
typelogic

Ответы:


41

Это должно сделать трюк:

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

Используйте Vim, это лучше для вашего здоровья. :-)

Опция oft-overlooked позволяет сделать так, +чтобы -execвсе имена файлов (вплоть до ограничения длины строки) отображались в одной строке, т.е. вы все равно получаете все файлы, открытые в одном vim сеансе (навигация с помощью :nдля следующего и :Nдля предыдущего файла).

При этом vim -pвы получаете вкладку файла для каждого файла. Проверьте :help tab-page-commandsдля более подробной информации.

При этом vim -oвы получите горизонтально разделенные окна для каждого файла, vim -Oвертикально разделенные окна. Проверьте :help window-move-cursorдля более подробной информации.

Обратите внимание, что предыдущая версия этого ответа vim $(find . -name "*.txt")не работает с пробелами в именах файлов и имеет последствия для безопасности.

Пайпинг в xargs viдает Warning: Input is not from a terminalплюс плюс терминал с полностью поддельным поведением впоследствии. Пользователь объяснил, почему в комментарии ниже, и немного больше объяснений в этом вопросе .


4
Не знаю, сколько вы знаете о vim, но мне / навсегда / понадобилось выяснить, что: n показывает следующий файл и: N показывает предыдущий.
zpletan

4
@DevSolar: Vim ожидает, что его stdin будет таким же, как его управляющий терминал, и выполняет различные связанные с терминалом ioctl на stdin напрямую. (Вы можете посчитать это ошибкой. Vim, безусловно, может открыть /dev/ttyи вызвать ioctl () для этого; просто лень это делать.) При вызове xargs vim получает в /dev/nullкачестве стандартного ввода, которое просто игнорирует ioctl управления терминалом.
благодарность

3
@zpletan: vim -pесли вы хотите вкладки файлов. ( gtи gTдля навигации, или щелкните мышью.)
grawity

2
К вашему сведению, чтобы избежать предупреждения при передаче по трубопроводу vim, просто укажите -в качестве первого аргумента, как в echo foobar | vim -.
Конрад Рудольф

2
@Konrad Rudolph: find . -name "*.txt" | vim -дает вам сеанс vim для неназванного файла, содержащего имена найденных файлов, что не является тем, о чем просил OP ...
DevSolar


1

Кроме того, если вы хотите, чтобы они открывались по одному, вы также можете использовать find -exec или использовать простой цикл for. Отредактировано согласно комментарию ceving.

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

или

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

... но зачем тебе это делать?
DevSolar

@DevSolar Первый - указать на возможность поиска, второй - цикл общего назначения. Может быть, вы хотите что-то сделать с каждым файлом, прежде чем редактировать его.
OldWolf

Вы когда-нибудь пробовали второе? Первое: find возвращает текущий каталог, потому что -nameотсутствует. И второе: команда с треском проваливается, как только имя файла содержит пробел. -1 за опрометчивый ответ.
выступление

На самом деле, тема пробелов в именах файлов относится и к моему ответу. Я даже не могу придумать, как правильно с ними обращаться, не превращая его из командной строки в небольшой собственный скрипт. Есть веская причина, почему пробелы в именах файлов не рекомендуется.
DevSolar

@ceving Действительная точка. Я предположил, что оригинальная находка постеров действительна для его нужд. Редактирование.
OldWolf,

0

Если вы уже набрали свою findкоманду, я обнаружил, что ее гораздо проще использовать xargsдля открытия результатов поиска:

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

-pОпция указывает Vim , чтобы открыть каждый файл в новой вкладке. Я считаю это более удобным, чем просто использование буферов, но если вы этого не сделаете, просто отключите эту опцию.


спасибо, я подключил его, чтобы найти, поэтому моя команда была: найти имя файла | xargs vim -p
Талсибони

0

Для того, чтобы изменить все *.txt, что вы можете просто запустить: vim *.txt. Чтобы редактировать возвращенные файлы find, читайте дальше.


В Unix / macOS вы можете использовать findс BSD xargs(см . man xargs:), например

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

-o( xargs): Заново открыть стандартный ввод как / dev / tty в дочернем процессе перед выполнением команды.

Связано: Терминал заблокирован после вызова Vim с xargs на Vim.SE.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.