коснуться всех папок в каталоге

14

Я пытаюсь обновить метки времени всех папок в cwd, используя это:

for file in `ls`; do touch $file; done

Но это не похоже на работу. Есть идеи почему?

javamonkey79
источник

Ответы:

21

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

$ find . -maxdepth 1 -mindepth 1 -type d -exec touch {} +

Или , если ваша findреализация не поддерживает нестандартные -mindepth/ -maxdepthпредикаты:

$ find . ! -name . -prune -type d -exec touch {} +

Эта:

$ touch -c -- */

Должен работать в большинстве оболочек, за исключением того, что:

  • это будет также touch символические ссылки на каталоги в дополнение к простым каталогам
  • он пропустит скрытые
  • если нет никакого каталога или символьной ссылки на каталог, это создаст файл с именем , *отличными от снарядов csh, tcsh, zsh, fishили Thompson оболочка (которая будет сообщать об ошибке , а). Здесь мы используем, -cчтобы обойти это, хотя это может все еще touchназываться не каталогом файла *.

С zsh, в touchкаталоги только, в том числе скрытых из них:

touch -- *(D/)
Михаил Мрозек
источник
О чем {} \ +?
javamonkey79
3
Это {} \+специальный findсинтаксис - читайте справочную страницу для получения дополнительной информации. Я думаю, что touch -c ./*/будет работать так же.
jw013
2
Вы должны включить -maxdepth 1в команду, чтобы findне переходить в подпапки. OP, кажется, хочет коснуться только тех папок в cwd, а не подпапок.
Стивен Понедельник
1
@ jw013 Это было бы - вы продолжаете добавлять хорошие идеи к ответам других людей :)
Майкл Мрозек
Почему бы вам избежать символа +? Есть ли оболочки, которые это интерпретируют?
Witiko
11

Пытаться

touch ./*

Это позволяет избежать ненужного forцикла, который порождает новый процесс для каждого отдельного файла, и работает для всех имен файлов, даже с именами с пробелами или с похожими параметрами -t. Единственный раз, когда это не сработает, это если у вас нет (не точечных) файлов в каталоге, и в этом случае вы в конечном итоге создадите файл с именем *. Чтобы избежать этого, в конкретном случае touchбольшинства реализаций есть -cопция (также называемая --no-createв версиях GNU), чтобы не создавать несуществующие файлы, т.е.

touch -c ./*

Смотрите также ссылки хорошие в ответ jasonwryan в так же как это одно .

jw013
источник
1
Что будет, если у вас 1 миллион папок на cwd?
Стивен Понедельник
Если вы сталкиваетесь с проблемами типа «список аргументов слишком длинный», то, вероятно, лучше переключиться на «более тяжелые» инструменты, например find . -type d -maxdepth1 -print0 | xargs -0 touch, или ответ MichaelMrozek выше.
jw013
7

Вы не должны пытаться анализировать выводls .

Кроме того, вы должны указать свои, "$file"чтобы захватить любые пробелы. См. Http://www.grymoire.com/Unix/Quote.html.

Нечто подобное может достичь того, что вы ищете:

for file in *; do touch "$file"; done

Посмотрите первые две ловушки Bash для более подробного объяснения.

jasonwryan
источник
2
Близко, но не совсем. А touch ./*должно работать в большинстве случаев. forЦикл действительно не нужен, поскольку он touchможет принимать несколько файлов, и вам нужно ./обрабатывать файлы с такими именами, как нужно --help. Это хороший ресурс на эту тему.
jw013
Почему «*» работает?
javamonkey79
@ javamonkey79 Это оболочка универсализации .
jw013
1
@ jw013 Отличный момент: и спасибо за ссылку Уилера.
Джейсонвриан
Обратите внимание, что *не захватывает файлы и каталоги, чье имя начинается с точки. Один из способов исправить это - включить dotglobопцию оболочки через shopt -s dotglob.
Witiko