начинающих пользователей Unix, которые только что узнали о перенаправлении ввода-вывода ( и
>
)
часто пробуют такие вещи, как
command … input_file > the_same_file
или
command … < file > the_same_file
или, что почти то же самое,
cat file | command … > the_same_file
( grep
, sed
, cut
, sort
и spell
являются примерами команд
, которые у людей возникает соблазн использовать в подобных конструкциях.)
Пользователи с удивлением обнаруживают, что в этих сценариях файл становится пустым.
Нюанс, который, похоже, не упоминается в другом ответе, можно найти в первом предложении раздела Redirection bash (1) ]:
Перед выполнением команды ее ввод и вывод могут быть перенаправлены с использованием специальной записи, интерпретируемой оболочкой.
Первые пять слов должны быть выделены жирным шрифтом, курсивом, подчеркнуты, увеличены, мигают, окрашены в красный цвет и отмечены значком , чтобы подчеркнуть тот факт, что оболочка выполняет запрошено перенаправление (я) перед выполнением команды . И помните также
Перенаправление вывода заставляет файл… открываться для записи…. Если файл не существует, он создается; если он существует, он обрезается до нулевого размера.
Итак, в этом примере:
список сортировки> список
оболочка открывает файл списка
для записи, усекая его
(т. Е. Отбрасывая все его содержимое) перед запуском программы sort
.
Естественно, восстановить данные невозможно.
Можно наивно ожидать, что
tr "[: upper:]" "[: lower:]" poem
может быть лучше.
Поскольку оболочка обрабатывает перенаправления слева направо,
она открывает стихотворение
для чтения (для стандартного ввода tr
)
прежде, чем он откроет его для записи (для стандартного вывода).
Но это не помогает.
Несмотря на то, что эта последовательность операций дает два дескриптора файла,
они оба указывают на один и тот же файл.
Когда оболочка открывает файл для чтения, содержимое все еще там,
, но оно все еще затирается перед выполнением программы.
Решения включают:
Проверить, имеет ли программа, которую вы запускаете,
собственную внутреннюю возможность указывать, куда идет вывод.
Это часто обозначается токеном -o
(или - output =
).
В частности,
sort roster -o roster
примерно эквивалентен
sort roster> roster
, за исключением первого случая, программа sort
открывает выходной файл.
И он достаточно умен, чтобы не открывать выходной файл
до тех пор, пока после он не прочитает все входные файлы.
Аналогичным образом, по крайней мере, в некоторых версиях sed
есть параметр -i
(редактировать i n место)
, который можно использовать для записать вывод обратно во входной файл
(опять же, после , все входные данные были прочитаны).
Редакторы, такие как ed
/ ex
, emacs
, pico
и vi
/ ] vim
позволяет пользователю редактировать текстовый файл и сохранять отредактированный текст в исходном файле.
Обратите внимание, что ed
(по крайней мере) можно использовать не интерактивно.
vi
имеет связанную функцию.
Если вы наберете :%! команда
Введите ,
он запишет содержимое буфера редактирования в команду
, прочитает вывод,
и вставит его в буфер (заменяющий исходное содержимое). Простой, но эффективный:
команда … входной_файл > временный_файл && mv временный_файл входной_файл
Недостатком этого является, input_file
- это ссылка,
она (возможно) будет заменена отдельным файлом.
Кроме того, новый файл будет принадлежать вам с защитой по умолчанию.
В частности, это несет в себе риск того, что файл станет доступным для чтения всем,
даже если исходный input_file
не был.
Варианты:
команда … input_file > temp_file && cp temp_file input_file && rm temp_file
temp_file
доступным для чтения всем.
Еще лучше: cp input_file temp_file && command … temp_file > input_file && rm temp_file
-a
или -p
на cp
, чтобы указать ему сохранять атрибуты.) command … input_file > temp_file &&
cp --attributes-only --preserve = all input_file temp_file &&
mv temp_file input_file
В этом блоге (редактирование файлов на месте) предлагается и объясняется
{rm input_file && команда …> входной_файл ; } input_file
Для этого требуется, чтобы команда
могла обрабатывать стандартный ввод
(но почти все фильтры могут).
Сам блог называет это рискованным кладжем и не рекомендует его использовать.
И это также создаст новый отдельный файл (ни с чем не связанный),
принадлежащий вам и с разрешениями по умолчанию.
В пакете moreutils есть команда под названием sponge
:
команда … input_file | губка the_same_file
См. этот ответ для получения дополнительной информации.
Вот кое-что, что стало для меня полной неожиданностью: синтаксическая ошибка говорит :
[Большинство этих решений] завершится ошибкой в файловой системе, доступной только для чтения, где «только для чтения» означает, что ваш
$ HOME
будет доступен для записи, {{1 }} но/ tmp
будет только для чтения (по умолчанию). Например, если у вас Ubuntu и вы загрузились в консоль восстановления, это обычно так. Кроме того, оператор здесь-документатам тоже не будет работать, поскольку он требует
/ tmp
для чтения / напишите , потому что он также запишет туда временный файл.
(см. этот вопрос включает выводstrace
'd)
В этом случае может работать следующее:
sort
или tr
без параметра -d
или -s
),
вы можете попробовать
команду … input_file | dd of = the_same_file conv = notruncСм. этот ответ и этот ответ для дополнительная информация, включая объяснение вышеизложенного, и альтернативы, которые работают , если ваша команда гарантированно произведет такой же объем выходных данных , как и вход или less (например,
grep
или cut
).
У этих ответов есть то преимущество, что они не требуют свободного места
(или требуют очень мало).
Ответы выше в форме
команда … input_file > temp_file &&…
четко требовать, чтобы в системе было достаточно свободного места, чтобы она могла
одновременно хранить весь входной (старый) файл и выходной (новый) файл;
это неочевидно для большинства другие решения
(например,, sed -i
и sponge
).
Исключение: сортировка… | dd…
, вероятно, потребуется много свободного места,
потому что sort
должен прочитать весь свой ввод, прежде чем он сможет записать какой-либо вывод,
и, вероятно, буферизует большую часть если не все эти данные во временном файле. команда … input_file 1 the_same_fileможет быть эквивалентным ответу
dd
выше.
Синтаксис n file
открывает именованный файл
в файловом дескрипторе n
как для ввода, так и для вывода , без усечения -
своего рода комбинация n
и n >
.
Примечание. Некоторые программы (например, cat
и grep
) могут отказываться запускаться в этом сценарии
, поскольку они могут обнаружить, что входные и выходные данные это один и тот же файл.
См. этот ответ
для обсуждения вышеизложенного,
и сценария, который заставляет этот ответ работать, если ваша команда гарантированно
производят тот же объем выходных данных, что и вход или меньше . Это была популярная тема на U&L; он рассматривается в следующих вопросах:
iconv
заменить входной файл преобразованным выходным? shuf file> file
пустой файл? sort
дает мне пустой файл? tr
stdout в файл … и это не считая суперпользователя или Ask Ubuntu. В этот ответ я включил много информации из ответов на вышеупомянутые вопросы , но не всю. (т.е. для получения дополнительной информации прочтите перечисленные выше вопросы и их ответы.)
P.S. У меня нет связи с блогом, который я цитировал выше.
Los archivos de registro se almacenan en /var/log
, por lo que realmente no es necesario ejecutar find
en todo el directorio raíz. Si insiste en hacerlo y desea excluir ese directorio para no recibir errores, su sintaxis debería ser:
find / -wholename /run -prune -o -type f -name '*.log' -print
Ese directorio es el punto de montaje para FUSE y no contiene ningún archivo de registro y /run
en sí mismo tiene directorios (al menos en Centos, Fedora y RHEL )dentro de los cuales dará errores de permiso, por lo que el comando anterior excluir el directorio por completo. No tengo instalado Mint, por lo que puede editar el comando para podar más bajo hasta que reciba errores.
Además, una cosa a tener en cuenta es que los archivos de registro no siempre terminan en .log
como messages
, dmesg
, cron
y secure
.
Solo haz:
find / -type f -name '*.log' 2>/dev/null
o
find /var -type f -name '*.log'
hasta donde deben estar los registrosvar
La expresión correcta para evitar los mensajes de error de "permiso denegado" es:
find <root-path> ! -readable -prune -o <rest of your find arguments>
Aplicar eso a tu respuesta original de la tarea produciría:
find / ! -readable -prune -o -type f -name "*.log"
Eso debería satisfacer su requisito de "ensamblar un comando simple e inteligente". También cumple con el requisito "que no solo filtra a ciegas los mensajes de error" porque solo filtra cosas ilegibles. Su requisito final "pero solo omite aquellos lugares donde realmente no tiene sentido mirar" es otro asunto completamente diferente, y sería una buena pregunta por separado, a saber, '¿Hay alguna forma de que una secuencia de comandos encuentre el directorio raíz de registro del sistema predeterminado?, en el sistema particular en el que se ejecuta el script?'. No tengo conocimiento de una variable de entorno para eso.