У меня есть много текстовых файлов в каталоге, и я хочу удалить последнюю строку каждого файла в каталоге.
Как мне это сделать?
text-processing
files
ThehalfarisedPheonix
источник
источник
Ответы:
Если у вас есть доступ к
vim
, вы можете использовать:источник
Вы можете использовать этот хороший oneliner, если у вас есть GNU
sed
.Он удалит последнюю строку каждого не скрытого файла в текущем каталоге. Переключатель
-i
для GNUsed
означает, что он работает на месте и'$ d'
выдает командуsed
на удаление последней строки (что$
означает последнюю иd
означает удаление).источник
-i
GNUism, так что это спорный вопрос, но я потерял бы свою старую бороду, если бы не указал, что некоторые старые версииsed
не позволяют вам ставить пробелы между$
иd
(или, в общем между шаблоном и командой).*(.)
для перемещения обычных файлов, я не знаю о других оболочках.Все остальные ответы имеют проблемы, если каталог содержит что-то отличное от обычного файла или файл с пробелами / символами новой строки в имени файла. Вот то, что работает независимо от:
find "$dir" -type f
: найти файлы в каталоге$dir
-type f
которые являются обычными файлами;-exec
выполнить команду для каждого найденного файлаsed -i
: редактировать файлы на месте;'$d'
: удалить (d
) последнюю ($
) строку.'+'
: сообщает find для добавления аргументовsed
(немного эффективнее, чем выполнение команды для каждого файла отдельно, благодаря @zwol).Если вы не хотите спускаться в подкаталоги, вы можете добавить аргумент
-maxdepth 1
вfind
.источник
find
этом написано более эффективноfind $dir -type f -exec sed -i '$d' '{}' '+'
.)-print0
нет в полной команде, зачем ставить это в объяснение?-depth 0
не работает (findutils 4.4.2), вместо этого должно быть-maxdepth 1
.-exec
.Использование GNU
sed -i '$d'
означает чтение полного файла и создание его копии без последней строки, в то время как было бы намного эффективнее просто обрезать файл на месте (по крайней мере, для больших файлов).С GNU
truncate
вы можете сделать:Если файлы относительно малы, это, вероятно, будет менее эффективным, так как для каждого файла выполняется несколько команд.
Обратите внимание, что для файлов, которые содержат дополнительные байты после последнего символа новой строки (после последней строки) или другими словами, если у них есть последняя строка без разделителя , то в зависимости от
tail
реализации,tail -n 1
будут возвращаться только эти дополнительные байты (например, GNUtail
), или последняя (правильно разделенная) строка и эти лишние байты.источник
|wc -c
вtail
вызове? (или а${#length}
)${#length}
не будет работать, так как он подсчитывает символы, а не байты, и$(...)
удаляет завершающий символ новой строки, поэтому${#...}
отключается на единицу, даже если все символы являются однобайтовыми.Более портативный подход:
Я не думаю , что это нуждается в каких - либо объяснениях ... кроме того, возможно , что в этом случае
d
такой же , как с$d
тех порed
по умолчанию выбирает последнюю строку.Это не будет выполнять рекурсивный поиск и не будет обрабатывать скрытые файлы (также называемые точечными файлами).
Если вы хотите отредактировать их, также смотрите Как сопоставить * со скрытыми файлами в каталоге
источник
[[]]
на,[]
то это будет полностью POSIX-совместимым. ([[ ... ]]
это Bashism.)[[
это не чушь )POSIX-совместимый однострочник для всех файлов, рекурсивно начинающихся в текущем каталоге, включая dot-файлы:
Только для
.txt
файлов, не рекурсивно:Также см:
источник