Нет не -хакерских способов перенаправить вывод другого процесса в другое место [1], но если a)вы не планируете когда-либо возвращать свой процесс на передний план и b)в порядке с другим процессом (легким -весомымcat
)также работающим в течение всего времени работы вашей программы, это может привести к:
{ your_program... & } | (trap : INT; cat & sleep 5; kill $!; cat >/dev/null &)
Вы можете захотеть перенаправить как stderr, так и stdout вашей программы в конвейер с помощью your_program 2>&1
.
[1] Возможный хакерский способ — подключиться к нему с помощью отладчика и перенаправить его вывод изнутри.
Вам действительно не нужны для этого внешние утилиты. Вы можете продвинуться довольно далеко, объединив набор стандартных команд, которые вы всегда можете запомнить, сохранив их в сценарии или функции оболочки.
Чтобы обнаружить дубликаты, вы можете хранить все пути к файлам в ассоциативном массиве с указанием размера и имени файла. Но поскольку вы указываете, что у вас большая коллекция файлов, я предлагаю вместо этого использовать сортировку. Затем отсортируйте второй раз с опцией уникальный , чтобы сравнение обоих результатов дало вам дубликаты.
Вы хотите использовать результат первого сортирования дважды. Я могу использовать для этого временный файл; именованные каналы, fifo и тому подобное не требуют меньше усилий для этой простой работы. Команда mktemp
напечатает для вас безопасное уникальное имя файла в каталоге /tmp/
. С помощью команды , заменяющей конструкцией $(...)
, вы можете присвоить это имя переменной с именем tmp
или любым другим. Повторите это, чтобы знать, что вы делаете.
Теперь вы хотите использовать 2 ключевых поля :размер и имя файла, а также вам нужен полный путь. Для удобства косая черта /
не является допустимым символом имени файла :, она зарезервирована для разделения имен каталогов и имен файлов. Как следствие, вы можете использовать /
в качестве разделителя между этими 3 полями. Действие -printf
команды find
может дать вам :найти все-type f
(файлы )и распечатать их размер %s
, имя файла %f
и полный путь %p
, все разделенные по /
. Полные пути будут содержать больше косых черт,но мы знаем, что только первые 2 разделителя косой черты, которые мы явно указываем в формате -printf
, являются нашими.
Направить |
вывод команды find
, список размеров, имен файлов и полных путей, в команду sort
. Скажите ему, что поля разделены косой чертой:-t /
и что ключ находится в первых двух полях:-k 1,2
. Вы можете сохранить отсортированный список сразу во временном файле, но я решил позволить сделать это команде tee
, потому что таким образом вы можете оставить открытым один конвейер для повышения производительности.
Направить |
отсортированный список в tee
, который сохраняет его копию в файле с заданным именем "$tmp"
и как бы повторяет канал до следующего канала.
Направить эхо|
tee
отсортированного списка второму sort
по тем же ключам, но теперь сделать вывод -u
или --unique
в ключах сортировки.
Передать |
список уникальных записей размера+имени файла команде diff
в качестве первого ввода-
(stdin)и использовать временный файл "$tmp"
в качестве второго. Обычно diff
добавляет некоторую разметку к своему выводу, чтобы вы могли определить природу изменений. Но нам это не нужно, и это загромождает вывод для наших нужд. Мы знаем, что каждая запись уникального списка также находится в полном списке. Нам просто нужны простые дополнительные строки, которые есть только в полном списке. Это то, о чем просят опции команды diff
.
Приведенная выше команда выведет, надеюсь, краткий список файлов, у которых есть дубликаты. Один из каждого набора дубликатов опущен, потому что он все еще фигурирует в уникальном списке. Чтобы обработать каждую запись этого списка и воздействовать на его последнюю часть, полное имя пути, мы передаем |
его в конструкцию while read
. Это сохраняет каждую строку под заданным именем параметра dupl
. В синтаксисе расширения параметра bash #
мы опускаем префикс */*/
, то есть размер плюс имя файла с разделителями косой черты /
,и остается полный путь к дубликату файла. Я предлагаю вам сначала выполнить полную команду с echo
и заменить ее командой удаления rm
после тщательной проверки, или, что еще лучше, использовать одну из утилит корзины для перемещения дубликатов к вам или Trash
, поэтому что ваш каталог очищен, но ничего не потеряно.
tmp=$(mktemp)
echo temp file is "$tmp"
find -type f -printf "%s/%f/%p\n" |
sort -t / -k 1,2 |
tee "$tmp" |
sort -t / -k 1,2 -u |
diff --new-line-format="%L" --unchanged-line-format="" - "$tmp" |
while read dupl;do echo "${dupl#*/*/}"; done
rm "$tmp"
Приберитесь за собой и очистите временный файл "$tmp"
.