find -exec ls -lR {} \; возвращает каждый элемент дважды

Предпосылки : В настоящее время я пишу сценарий архивирования, который создает gzipped tarball из некоторых папок и их содержимого. Он должен иметь возможность синхронизировать gzipped-архивы с источниками без разжатия архивов или сжатия источников. Для этого tar -ztvf решение синхронизирует выход ls -l с выходом tar -ztvf .

Обе команды возвращают аналогичный вывод, однако они немного отличаются. Большинство этих различий можно сортировать с помощью регулярных выражений или cut . Одна вещь, которую я не мог легко решить, – это указать путь к файлам относительно запрошенного каталога с максимальной глубиной.

Чтобы преодолеть эту проблему, я использовал find чтобы найти каждый файл, и передал их в ls с помощью команды:

 find Webcam -exec ls -lR --time-style="+%Y-%m-%d %H:%M" {} \; | cut -f1,3- -d" " | sed "s/ /\//2" | sed "s/ \+/ /g" 

где большая часть конвейера служит для форматирования, find Webcam -exec ls -lR {} \; является проблематичной частью, а Webcam – тестовой папкой. Вывод этой команды следующий:

 -rw-r--r-- debian/debian 162406 2014-04-12 13:42 2014-04-12-134210.jpg -rw-r--r-- debian/debian 116247 2014-08-09 16:38 2014-08-09-163849.jpg -rw-r--r-- debian/debian 96597 2015-03-15 19:39 2015-03-15-193905.jpg -rw-r--r-- debian/debian 100795 2015-04-29 20:23 2015-04-29-202242.jpg -rw-r--r-- debian/debian 97120 2015-08-02 13:42 2015-08-02-134230.jpg -rw-r--r-- debian/debian 123835 2015-08-27 23:03 2015-08-27-230306.jpg -rw-r--r-- debian/debian 97120 2015-08-02 13:42 Webcam/2015-08-02-134230.jpg -rw-r--r-- debian/debian 100795 2015-04-29 20:23 Webcam/2015-04-29-202242.jpg -rw-r--r-- debian/debian 116247 2014-08-09 16:38 Webcam/2014-08-09-163849.jpg -rw-r--r-- debian/debian 96597 2015-03-15 19:39 Webcam/2015-03-15-193905.jpg -rw-r--r-- debian/debian 162406 2014-04-12 13:42 Webcam/2014-04-12-134210.jpg -rw-r--r-- debian/debian 123835 2015-08-27 23:03 Webcam/2015-08-27-230306.jpg 

Теперь вывод похож на вывод tar -ztvf :

 -rw-r--r-- debian/debian 162406 2014-04-12 13:42 Webcam/2014-04-12-134210.jpg -rw-r--r-- debian/debian 116247 2014-08-09 16:38 Webcam/2014-08-09-163849.jpg -rw-r--r-- debian/debian 96597 2015-03-15 19:39 Webcam/2015-03-15-193905.jpg -rw-r--r-- debian/debian 100795 2015-04-29 20:23 Webcam/2015-04-29-202242.jpg -rw-r--r-- debian/debian 97120 2015-08-02 13:42 Webcam/2015-08-02-134230.jpg -rw-r--r-- debian/debian 123835 2015-08-27 23:03 Webcam/2015-08-27-230306.jpg 

с очевидным недостатком ls перечисляющим каждый найденный предмет дважды, один раз с требуемым путем и один раз без него. Как я могу «исправить» ls чтобы перечислить каждый элемент дважды?

Дополнительное понимание характера этой ошибки (например, то, что происходит под капотом) более чем приветствуется, в то время как более практичные способы решения всей проблемы архивирования также приветствуются в качестве побочных замечаний. Однако сейчас я рассматриваю это как проблему, которую я бы хотел решить, поэтому основное внимание следует уделить ограничению вывода ls .

  • Возможно ли интегрировать файлы zip и tar.gz в качестве каталога в файловую систему
  • Можно ли перечислить все файлы в файле * .tar.gz без сканирования всего содержимого?
  • Будет ли tar -cvzf packed.tar.gz mydir учитывать скрытые файлы?
  • Извлеките TAR на SD-карту и проверьте содержимое впоследствии
  • Резервное копирование размонтированного устройства в файл tar
  • Может ли `tar -list -v` указать размер файла в формате для чтения?
  • Возобновляемый архив
  • Могу ли я взять вывод ldd и загрузить файлы .so?
  • 3 Solutions collect form web for “find -exec ls -lR {} \; возвращает каждый элемент дважды”

    Проблема заключается в том, что find также находит каталог Webcam и запускает ls Webcam котором перечислены все файлы. Чтобы перечислять только файлы, а не каталоги, скажите find

     -type f 

    Ваша проблема в том, что ls -lR будет выполняться для всех файлов (которые будут отображать файлы) и каждого каталога (который отобразит содержимое каталога). Если ваша иерархия каталогов не будет плоской, но будет содержать подкаталоги, это будет отображать содержимое еще чаще, поскольку -R указывает ls на повторное перемещение подкаталогов. Вместо этого вы должны вызвать find следующим образом:

    1. find . -type f -exec ls -l {} find . -type f -exec ls -l {} , который будет отображать только файлы.
    2. find . -exec ls -dl {} find . -exec ls -dl {} , который отображает как файлы, так и каталоги.

    Основная причина этой проблемы удивительно короткая:. (да: точка).

    Поймите, что find (без каталога) эквивалентно find . , От man find :

    Если пути не заданы, используется текущий каталог.

    И когда вы выполняете find . точка отображается в сгенерированном списке
    (Использование только четырех файлов с разными именами, чтобы сделать их простыми):

     $ find ### Works the same with or without the dot. . ./2014-08-09-163849.jpg ./2014-04-12-134210.jpg ./Webcam ./Webcam/2015-04-29-202242.jpg ./Webcam/2015-08-27-230306.jpg 

    И тогда вы даете этот список ls -R (рекурсивно).
    Просто точка будет воспроизводить все файлы:

     $ ls -1R . ### The 1 will make the list 1 column. .: Webcam 2014-04-12-134210.jpg 2014-08-09-163849.jpg ./Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg 

    Поэтому неудивительно, что все файлы появляются дважды (один раз для точки, один раз из find).

     $ find -exec ls -1R {} \; .: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam ./Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg ./2014-08-09-163849.jpg ./2014-04-12-134210.jpg ./Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg ./Webcam/2015-04-29-202242.jpg ./Webcam/2015-08-27-230306.jpg 

    Решения

    Удалите точку (используйте \( ! -name . -prune \) -a ).

    Удалите точку из списка найденных файлов из find:

     $ find . \( ! -name . -prune \) -a -print ./2014-08-09-163849.jpg ./2014-04-12-134210.jpg ./Webcam 

    Затем вы можете использовать рекурсивный ls -R :

     $ find . \( ! -name . -prune \) -a -exec ls -1R {} \; ./2014-08-09-163849.jpg ./2014-04-12-134210.jpg ./Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg 

    Избегайте рекурсивных ls (проще, но требует ls -d ).

    Не используйте рекурсивный ls -R (также с опцией -d чтобы не разворачиваться в директории), и можно find прохождение дерева, чтобы найти все файлы:

     $ find . ! -path . -exec ls -1d {} \; ./2014-08-09-163849.jpg ./2014-04-12-134210.jpg ./Webcam ./Webcam/2015-04-29-202242.jpg ./Webcam/2015-08-27-230306.jpg 

    архивирование

    Конечно, для конкретного использования архивирования:
    вам не нужны имена каталогов, просто имена файлов полного пути:

     $ find . ! -path ./ -type f -a -exec ls -1R {} \; ./2014-08-09-163849.jpg ./2014-04-12-134210.jpg ./Webcam/2015-04-29-202242.jpg ./Webcam/2015-08-27-230306.jpg 

    О find dir (не точка).

    Если вы используете путь, проблема будет такой же, если глубина каталогов больше единицы.

    Это не вызовет проблемы:

     $ find Webcam -exec ls -1R {} \; Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg Webcam/2015-04-29-202242.jpg Webcam/2015-08-27-230306.jpg - $ find Webcam -exec ls -1R {} \; Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg Webcam/2015-04-29-202242.jpg Webcam/2015-08-27-230306.jpg 

    Однако увеличение глубины на единицу (cd ..) будет:

     $ cd .. $ find jpg -exec ls -1R {} \; jpg: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/2014-08-09-163849.jpg jpg/2014-04-12-134210.jpg jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg - $ cd .. $ find jpg -exec ls -1R {} \; jpg: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/2014-08-09-163849.jpg jpg/2014-04-12-134210.jpg jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg - $ cd .. $ find jpg -exec ls -1R {} \; jpg: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/2014-08-09-163849.jpg jpg/2014-04-12-134210.jpg jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg - $ cd .. $ find jpg -exec ls -1R {} \; jpg: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/2014-08-09-163849.jpg jpg/2014-04-12-134210.jpg jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg 

    который не будет срабатывать:

     $ find jpg \( ! -path ./jpg -prune \) -exec ls -1R {} \; jpg: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg - $ find jpg \( ! -path ./jpg -prune \) -exec ls -1R {} \; jpg: 2014-04-12-134210.jpg 2014-08-09-163849.jpg Webcam jpg/Webcam: 2015-04-29-202242.jpg 2015-08-27-230306.jpg 

    Я настаиваю на том, что использование двух рекурсивных инструментов очень плохое .

    Перейдите на более простую структуру, например, find jpg -ls или попробуйте предоставить решение для листинга, похожее на echo ** :

     $ (shopt -s globstar nullglob; printf '%s\n' jpg/**/*) jpg/2014-04-12-134210.jpg jpg/2014-08-09-163849.jpg jpg/Webcam jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg - $ (shopt -s globstar nullglob; printf '%s\n' jpg/**/*) jpg/2014-04-12-134210.jpg jpg/2014-08-09-163849.jpg jpg/Webcam jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg - $ (shopt -s globstar nullglob; printf '%s\n' jpg/**/*) jpg/2014-04-12-134210.jpg jpg/2014-08-09-163849.jpg jpg/Webcam jpg/Webcam/2015-04-29-202242.jpg jpg/Webcam/2015-08-27-230306.jpg 
    Interesting Posts

    Как создать фальшивое событие inotify на debian?

    Возможно ли установить программу на внешний диск?

    Простой сценарий оболочки с арифметической проблемой … ** дает мне проблемы

    -bash: / usr / sbin / useradd: Ошибка ввода / вывода. Что это значит?

    Должен ли я использовать одиночные или двойные угловые скобки для перенаправления на / dev / null?

    Инструменты для анализа автоматически генерируемых HTTP-индексов?

    Установка qemu-img на ubuntu 11.04

    7z из сценария bash не исключает каталогов

    Не удалось войти в сервер Cockpit – не удалось установить ограничение для «nofile»,

    Как регистрировать доступ всех доменов?

    Как превратить мой Linux-ноутбук в беспроводной ретранслятор?

    Не удается найти аудиооборудование для моей рабочей станции

    Как настроить обои с двумя мониторами (Ubuntu / NVIDIA)?

    OEL6 Медленная загрузка && Миллионы файлов сокетов в / tmp / orbit-gdm

    Linux-процесс "планирование"

    Linux и Unix - лучшая ОС в мире.