Я хочу удалить конечные пробелы из всех файлов в рекурсивной иерархии каталогов. Я использую это:
find * -type f -exec sed 's/[ \t]*$//' -i {} \;
Это работает, но также удаляет конечные пробелы из найденных двоичных файлов, что нежелательно.
Как мне сказать, find
чтобы избежать запуска этой команды на двоичных файлах?
file
которые могут проверять данные.Ответы:
Вы можете попытаться использовать команду Unix,
file
чтобы помочь идентифицировать файлы, которые вам не нужны, но я думаю, что было бы лучше, если бы вы явно указали, какие файлы вы хотите использовать, а не те, которые вы не хотите.чтобы избежать попадания в файлы управления исходным кодом, вы можете захотеть что-то вроде
Вам могут понадобиться или не понадобиться некоторые обратные слеши в зависимости от вашей оболочки.
источник
-i
опции sed . Трудно написать команду переносимой оболочки, не так ли?Это можно сделать из командной строки.
источник
Самый простой и самый переносимый ответ - запустить это:
Ниже я объясню, почему, где я также показываю, как это сделать, используя только командную строку, а также как обращаться с текстовыми файлами trans-ASCII, такими как ISO-8859-1 (Latin-1) и UTF-8, которые после -Ассии пробелов в них.
Остальная часть истории
Проблема в том, что find (1) не поддерживает
-T
оператор filetest и не распознает кодировки, если он это сделал - что вам абсолютно необходимо для обнаружения UTF-8, де-факто стандартной кодировки Unicode.Что вы можете сделать, это запустить список имен файлов через слой, который выбрасывает двоичные файлы. Например
Однако теперь у вас есть проблемы с пробелами в ваших именах файлов, поэтому вам нужно опоздать с нулевым завершением:
Еще одна вещь, которую вы можете сделать, это не использовать,
find
ноfind2perl
, поскольку Perl-T
уже понимает :И если вы хотите, чтобы Perl предполагал, что его файлы находятся в UTF-8, используйте
Или вы можете сохранить полученный скрипт в файле и отредактировать его. Вы действительно должны не просто запустить
-T
filetest для любого старого файла, а только для тех, которые являются простыми файлами, как определено вначале-f
. В противном случае вы рискуете открыть специальные устройства, заблокировать на пятерках и т. Д.Однако, если вы собираетесь делать все это, вы можете вообще пропустить sed (1). Во-первых, он более переносим, поскольку POSIX-версия sed (1) не понимает
-i
, а все версии Perl - понимают . Версии sed для последних дней с любовью переняли очень полезную-i
опцию в Perl, где она впервые появляется.Это также дает вам возможность исправить ваши регулярные выражения. Вы действительно должны использовать шаблон, который соответствует одному или нескольким конечным горизонтальным пробелам, а не просто их нулю, или вы будете работать медленнее из-за ненужного копирования. То есть это:
должно быть
Однако, как получить sed (1), чтобы понять, что для этого требуется расширение,
-R
отличное от POSIX, как правило, для System System Unices, таких как Solaris или Linux, или-E
для BSD, таких как OpenBSD или MacOS. Я подозреваю, что это невозможно под AIX. Знаете, проще написать переносную оболочку, чем переносимый сценарий оболочки.Предупреждение о 0xA0
Хотя это единственные горизонтальные пробельные символы в ASCII, оба стандарта ISO-8859-1 и, следовательно, также Unicode имеют пробел NO-BREAK в кодовой точке U + 00A0. Это один из двух лучших не-ASCII символов, встречающихся во многих Unicode-корпусах, и в последнее время я видел, как многие люди ломали код регулярного выражения, потому что они забыли об этом.
Так почему бы тебе просто не сделать это:
Если у вас может быть UTF-8 файлов для решения, дополнения
-CSD
, и если вы работаете на Perl v5.10 или выше, вы можете использовать\h
для горизонтального пробельных и\R
для общего LineBreak, который включает в себя\r
,\n
,\r\n
,\f
,\cK
,\x{2028}
, и\x{2029}
:Это будет работать со всеми файлами UTF-8, независимо от их разрывов строк, избавляя от конечного горизонтального пробела (свойство символа Unicode
HorizSpace
), включая надоедливый пробел NO-BREAK, который возникает перед разрывом строки Unicode (включая комбинации CRLF) в конце каждой строки.Он также гораздо более переносим, чем версия sed (1), потому что существует только одна реализация perl (1), но много sed (1).
Основная проблема, которую я вижу, остается с find (1), поскольку в некоторых действительно непокорных системах (вы знаете, кто вы, AIX и Solaris) она не понимает
-print0
директиву со сверхкритическими параметрами . Если это ваша ситуация, то вы должны просто использоватьFile::Find
модуль из Perl напрямую и не использовать никаких других утилит Unix. Вот чистая Perl-версия вашего кода, которая не полагается ни на что другое:Если вы работаете только с текстовыми файлами ASCII или ISO-8859-1, это нормально, но если вы работаете с файлами ASCII или UTF-8, добавьте
-CSD
переключатели во внутреннем вызове Perl.Если у вас смешанные кодировки всех трех ASCII, ISO-8859-1 и UTF-8, то, боюсь, у вас есть другая проблема. :( Вам придется выяснить кодировку для каждого файла, и никогда не бывает хорошего способа угадать это.
Unicode Пробелы
Для записи, Unicode имеет 26 различных пробельных символов. Вы можете использовать в unichars утилиту для нюхать эти вне. Только первые три горизонтальных пробела встречаются почти всегда:
источник
GNU grep довольно хорошо определяет, является ли файл двоичным или нет. Помимо Solaris, я уверен, что есть другие платформы, которые не поставляются с GNU grep, установленным по умолчанию, но, как и Solaris, я уверен, что вы можете установить его.
Если вы в Солярисе, вы бы заменили
grep
на/opt/csw/bin/ggrep
.Эти
grep
флаги выполняют следующие действия :l
только списки имен файлов для сопоставления файлов,R
является рекурсивным,I
соответствует только текстовые файлы (игнорирует двоичные файлы), а такжеP
для Perl-совместимый синтаксис регулярных выражений.Часть perl изменяет файл на месте, удаляя все конечные пробелы / табуляции.
И наконец: если UTF8 является проблемой, ответ tchrist в сочетании с моим должен быть достаточным, при условии, что
grep
ваша сборка была построена с поддержкой UTF8 (хотя, как правило, сопровождающие пакетов пытаются предоставить такую функциональность).источник