Сортировать вывод find -exec ls


14

Возможно ли на выходе find … -exec ls -ls ;отсортировать по алфавиту, по имени файла?

Это моя команда cron:

find /home/setefgge/public_html -type f -ctime -1 -exec ls -ls {} \;

Эта команда работает нормально, по большей части. Но результаты не сортируются в какой-либо значимой последовательности. Было бы очень полезно, если бы они были отсортированы по полю имени файла.


1
Используете Zsh? ls -ls **/*(.)
Кевин

@Kevin Не совсем - lsсортировал бы.
Жиль "ТАК - перестань быть злым"

Ответы:


14

Я предполагаю, что имена ваших файлов не содержат символов новой строки.

find /home/setefgge/public_html -type f -ctime -1 -exec ls -nls {} + | sort -k 10

Использование +вместо ;завершения -execдействия ускоряет его, объединяя вызовы ls. Вы можете сортировать, пропуская через sortкоманду; скажите ему начать сортировку с 10-го поля (первые 9 - это метаданные: блоки, разрешения, количество ссылок, пользователь, группа, размер и 3 поля даты / времени). Опция -nпредписывает lsиспользовать числовые значения для пользователя и группы, что позволяет избежать риска имен пользователей или групп, содержащих пробелы.

В качестве альтернативы, с zsh вы можете без каких-либо допущений обойтись без имени, используя квалификаторы glob для сбора и сортировки файлов и многократного zargsзапуска, lsесли командная строка будет слишком длинной. Вам нужен GNU ls(в частности, его -fопция), чтобы избежать повторной сортировки ls(другой подход - эмулировать lsс помощью zsh zstat).

autoload -U zargs
zargs -- /home/setefgge/public_html/**/*(.c-2) -- ls -lnsf

Спасибо огромное! Использование первой команды, которую вы послали, делает сортировку. Будет ли число по-прежнему 10, если я буду использовать более короткий путь? Например, если я запускаю ту же команду из / home / setefgge, а не из public_html?
Май

@MaJ 10 - количество пропущенных полей, оно не имеет никакого отношения к размеру имени файла.
Жиль "ТАК - перестань быть злым"

Спасибо. Я ценю вашу помощь, а также помощь всех остальных. Я считаю эту проблему решенной. Моя команда cron теперь сортирует файлы. Я впервые отправил вопрос в Stackexchange. Я не вижу вариант "Решено". Если кто-то из вас знает, как опубликовать это как решенное, пожалуйста, сделайте это. Благодарность!
MaJ

@MaJ Самое близкое, что мы должны пометить как решенный вопрос, это пометить один из ответов как принятый. Только вы, спрашивающий, можете сделать это. Для этого нажмите на галочку рядом с ответом, который вам больше всего помог. Если вы примете ответ, вы получите еще 2 очка репутации, и после этого вы сможете проголосовать за посты; Вы можете проголосовать за все посты, которые показались вам полезными. Для получения дополнительной информации см. Страницу тура и справочную страницу о том, что, когда кто-то отвечает на ваш вопрос .
Жиль "ТАК - перестань быть злым"

1

Почему бы не передать результат поиска через сортировку, а затем выполнить ls для каждой из строк?

find . -type f -ctime -1 | sort | while IFS= read -r filename; do ls -ls "$filename"; done

1

У POSIX есть это, чтобы сказать о датах в ls -lсписке ong:

<date and time>Поле должно содержать соответствующую дату и временную метку , когда в последний раз был изменен файл. В локали POSIX поле должно быть эквивалентно выводу следующей команды date:

date "+%b %e %H:%M"

... если файл был изменен за последние шесть месяцев, или:

date "+%b %e %Y"

Принимая это во внимание и гарантируя, что если в имени файла есть какие-либо символы новой строки, они будут правильно добавлены в ls -qопцию, указанную также в POSIX , подготовить регулярное выражение для lsрезультата сравнительно легко find:

d=$(date "+%b %e") y=$(date --date=yesterday "+%b %e")
echo "$d" "$y"

###OUTPUT###
Jul  5 Jul  4

grepдля этого вы будете возвращать только те строки, которые содержат строки, представляющие либо сегодняшние, либо вчерашние даты. Следующая команда добавляет к этому немного:

ls -alRcq | sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

ls варианты состоят из:

  1. -a вернуть все файлы в каталоге, включая те, которые начинаются с .dot
  2. -l длинный список
  3. -R рекурсивный список всех дочерних каталогов
  4. -c отображать время модификации, а не время доступа
  5. -qвозвращать глобус оболочки ?вместо непечатных или \tab символов в имени файла

Эти результаты передаются по |pipeфайлу, sedкоторому соответствуют только:

  1. Пустая строка, предшествующая пути и следующей строке
  2. Строки, начинающиеся с - (другими словами - не dдля каталога), которые также содержат ваши date.
  3. Он не печатает строки пути, если только каталог, который они называют, на самом деле не содержит файлов, которые вы отфильтровали.

Вывод выглядит так:

ls -alRcq --color=always | 
sed "1H;/^-/!{/./d;N;h};/$d\|$y/!d;x;/\n/p;g"

###OUTPUT###
.:
-rw------- 1 mikeserv mikeserv   2086 Jul  4 10:52 .bash_history
-rw------- 1 mikeserv mikeserv   2657 Jul  4 15:20 .lesshst
-rw-r--r-- 1 mikeserv mikeserv    681 Jul  5 05:18 .zdirs
-rw------- 1 mikeserv mikeserv 750583 Jul  5 08:28 .zsh_history
-rw-r--r-- 1 mikeserv mikeserv    166 Jul  4 23:02 Terminology.log
-rw-r--r-- 1 mikeserv mikeserv 433568 Jul  4 13:34 shot-2014-06-22_17-10-16.jpg
-rw-r--r-- 1 mikeserv mikeserv 445192 Jul  4 13:34 shot-2014-06-22_17-11-06.jpg

./.cache/efreet:
-rw------- 1 mikeserv mikeserv  37325 Jul  4 22:51 desktop_localhost_C.eet
-rw------- 1 mikeserv mikeserv  37325 Jul  4 23:30 desktop_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 22:51 desktop_util_localhost_C.eet
-rw------- 1 mikeserv mikeserv  24090 Jul  4 23:30 desktop_util_localhost_en_US.eet
-rw------- 1 mikeserv mikeserv  16037 Jul  4 23:30 icon_themes_localhost.eet
-rw------- 1 mikeserv mikeserv   3117 Jul  4 23:30 icons___efreet_fallback_localhost.eet
-rw------- 1 mikeserv mikeserv 768039 Jul  4 23:30 icons_gnome_localhost.eet
-rw------- 1 mikeserv mikeserv  18589 Jul  4 23:30 icons_hicolor_localhost.eet

./.config:
-rw-r--r-- 1 mikeserv mikeserv   30 Jul  4 19:10 pavucontrol.ini

./.config/chrome:
-rw-r--r-- 1 mikeserv mikeserv 94332179 Jul  4 13:36 conf.tar.lz4.bak

Да, это даже работает с LS_COLORS - что, вероятно, является низким приоритетом для вас cron, но, эй, ваши варианты открыты.

В любом случае это дает некоторые существенные преимущества перед некоторыми другими возможными решениями.

  1. Во-первых, find+ lsвключает в себя несколько вызовов - это включает только один lsпроцесс, и именно поэтому он способен надежно сортировать все - что он делает по умолчанию - и такsort также становится вспомогательным.

  2. Любое решение , содержащее findи sortи lsв значительной степени делает все работы в два раза. lsи findбудет разрешать каждый путь и statкаждый файл. lsи sortоба будут сортировать все результаты. Лучше всего вместо этого использоватьls .

  3. Тогда, конечно, есть dateи sedчасти этого ответа. Важно отметить, что вы выполняете сложную часть и получаете сначала регулярное выражение - и только один раз - а потом вы только сокращаете один список результатов, а не говорите, получаете результаты, получаете результаты, сортируете результаты и сортируете результаты.

  4. Это не нарушает имена файлов, содержащие символы новой строки, как, вероятно, будут другие решения. Это решение имеет свои собственные предостережения, которые я объясню далее, но они незначительны и легко обрабатываются. На мой взгляд, это самое надежное решение здесь.

В двух случаях приведенная выше команда может вызвать проблемы. Первый включает ?глобусы в именах файлов - хотя это уже более надежное решение, чем любое другое, предлагаемое здесь, и вероятность того, что вы столкнетесь с чем-либо, сама ?по себе достаточно мала, но существует вероятность, что эти глобусы будут разрешены. может соответствовать более одного имени файла. Пожалуйста, посмотрите это для получения дополнительной информации по этому вопросу.

Другая возможность связана с ложным срабатыванием - например, если у вас есть имя файла, фактически совпадающее со dateстрокой, по которой мы ищем, grepно которое на самом деле не было изменено ни в один из этих дней. Я не рассчитываю на то, что это проблема, но, если это так, спросите об этом, и я, вероятно, могу помочь вам сделать регулярное выражение более конкретным, чтобы справиться с этим.


0

Вы можете использовать комбинацию find, xargs и ls.

Вот пример команды: find . -type f -print0 | xargs -0 ls -lt

  • find будет рекурсивно искать все файлы в текущем каталоге.
  • xargs передаст этот список файлов lsкоманде за один вызов (при условии, что findвозвращается меньше ARG_MAXфайлов).
  • ls -lt отсортирует эти файлы по времени и отформатирует вывод

Чтобы получить вашу систему, ARG_MAXвы можете набрать:

$ getconf ARG_MAX
> 2621440

-1
ls -l $(find /home/setefgge/public_html -type f -ctime -1 | sort)

1
lsвыполняет свою собственную сортировку, поэтому вывод результатов findсквозной передачи sortбесполезен. Кроме того, ваша команда изменяет имена файлов, содержащие пробелы (среди прочих), и завершится ошибкой, если слишком много имен файлов.
Жиль "ТАК - перестань быть злым"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.