iselect
предоставляет список вверх-вниз (в качестве входных данных из предыдущего канала), в котором пользователь может пометить несколько записей (в качестве выходных к следующему каналу):
# показать некоторые доступные исполняемые файлы, оканчивающиеся на '* sh *', для запуска через `whatis`
find / bin / sbin / usr / bin -maxdepth 1 -type f -executable - name '* sh' |
iselect -t "выбрать некоторые исполняемые файлы для запуска 'whatis' на ..." -a -m |
xargs -d '\ n' -r whatis {{ 1}}
Вывод после нажатия клавиши пробела для нескольких тегов в моей системе:
тире (1) - интерпретатор команд (оболочка)
ssh (1) - SSH-клиент OpenSSH (программа удаленного входа)
mosh (1) - мобильная оболочка с роумингом и интеллектуальным локальным эхом
yash (1) - POSIX-совместимая оболочка командной строки
vipe
позволяет редактировать в интерактивном режиме (с любимым текстовым редактором) что проходит через трубу. Пример:
# возьмите список исполняемых файлов с длинными именами из `/ bin`, отредактируйте этот
# список по мере необходимости с помощью` mcedit` и запустите `wc` на выходе.
find / bin -type f | grep '...............' | РЕДАКТОР = mcedit vipe | xargs wc
Вывод (после удаления некоторых строк в mcedit
):
378 2505 67608 /bin/ntfs-3g.secaudit
334 2250 105136 / bin / lowntfs-3g
67 952 27152 /bin/nc.traditional
126 877 47544 / bin / systemd-machine-id-setup
905 6584 247440 итого {{1} }
Примечание для push & pull:
iselect
начинается со списка, в котором ничего не выбрано . vipe
начинается со списка, в котором каждый показанный элемент будет отправлен через конвейер, если пользователь не удалит его. В дистрибутивах на основе Debian обе утилиты можно установить с помощью apt-get install moreutils iselect
.
Проблема в том, что ваша оболочка настраивает конвейер команд перед запуском команд. Дело не в «вводе и выводе», а в том, что содержимое файла исчезло еще до того, как tail даже запустится. Это выглядит примерно так:
>
для записи, усекая его хвост
. tail
запускается, открывает / home / pi / Documents / test
и ничего там не находит Существуют различные решения, но главное - понять проблему, что на самом деле происходит не так и Почему.
В результате будет получено то, что вы ищете,
echo "$(tail -n 50 /home/pi/Documents/test)" > /home/pi/Documents/test
Объяснение:
$ ()
называется подстановкой команд, которая выполняет tail -n 50 / home / pi / Documents / test
> / home / pi / Documents / test
перенаправляет вывод echo "$ (tail -n 50 / home / pi / Documents / test)"
в тот же файл. Поскольку вы видели основную проблему с перенаправлением оболочки, Вот альтернативный способ обрезать файл до последних 50 строк:
file=/path/to/the/file
n=$(( $(wc -l < "$file") - 50 ))
[[ $n -gt 0 ]] && sed -i 1,${n}d "$file"
Тяжелая работа выполняется (GNU) sed с функцией -i
«редактирование на месте», которая работает под обложками, создавая выходные данные во временном файле. Остальные строки настраивали математику для операции sed, а именно:
wc
), затем вычитайте 50; присвойте это n
. n
положительный, выполните команду sed, чтобы удалить строки с 1 по n. Это связано с тем, что bash сначала обрабатывает перенаправление с помощью >
, удаляя содержимое файла. Затем он выполняет команду. Если бы вы использовали >>
, последние 50 строк были бы добавлены в конец того, что в данный момент находится в файле. В этом случае одни и те же 50 строк будут повторяться дважды.
Команда работает должным образом при перенаправлении в другой файл. Вот один из способов записать последние 50 строк файла в файл с тем же именем:
tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 && mv /home/pi/Documents/test2 /home/pi/Documents/test
Сначала последние 50 строк записываются во временный файл, который затем перемещается с помощью mv
для замены исходный файл.
Как отмечено в комментариях, это не сработает, если файл все еще открыт. Перемещение файла также создает новый индексный дескриптор и может изменить владельца и разрешения. Лучше сделать это с помощью временного файла:
tail -50 /home/pi/Documents/test > /home/pi/Documents/test2 ; cat /home/pi/Documents/test2 > /home/pi/Documents/test
Временный файл также можно удалить, хотя каждый раз, когда это происходит, его содержимое будет перезаписано.
printf '%s\n' '1,$-50d' w | ed -s /home/pi/Documents/tes
printf
используется для передачи команд (по одной в строке) в ed
.Команды ed
:
1, $ - 50d
- удалить все, кроме последних 50 строк w
- записать измененный файл обратно на диск Есть перенаправления не используются, поэтому оболочка не может перезаписать выходной файл до того, как он будет прочитан.
Кроме того, в отличие от большинства форм редактирования «на месте» (которые обычно имитируют редактирование «на месте» путем создания временного файла и последующего его переименования поверх оригинала), ed
фактически редактирует исходный файл - поэтому он сохраняет тот же индексный дескриптор (а также владелец, группу и права доступа - временный файл + mv всегда изменяет индексный дескриптор, а может изменять другие в зависимости от обстоятельств).
На несколько ином треке вы можете использовать logrotate (8)
для регулярного резервного копирования файлов журнала в файлы с инкрементными именами и затем удалите старые.
Таким образом управляются основные файлы системного журнала, чтобы предотвратить их слишком длинный рост.