Как мне создать пустой файл (размером 0 байт) во всех каталогах?

Недавно на собеседовании меня спросили," как создать файл нулевого размера [I Думаете, это означает пустой файл] во всех папках файловой системы? " Я нашел вопрос немного странным, я подумал о цикле, чтобы перечислить все каталоги и использовать touch или возможно, перейдите в корневой каталог и используйте коснитесь с рекурсивной опцией. У вас есть идеи?

6
задан 18 April 2021 в 11:02

4 ответа

Это может быть ...

find . -type d -exec touch {}/emptyfile \;
  • -тип d означает «каталоги»
  • exec используйте команду touch и создайте файл с именем «emptyfile»
  • , {} заменяет то, что найдено в результате find . / должен сделать его действительным путем + filenane и экранированный; закрыть команду (иначе она станет "emptyfile;")

результат ...

rinzwind@schijfwereld:~/t$ mkdir 1 2 3 4 5 6 7 8 9 10
rinzwind@schijfwereld:~/t$ ls -ltr */*
ls: cannot access '*/*': No such file or directory
rinzwind@schijfwereld:~/t$ find . -type d -exec touch {}/emptyfile \;
rinzwind@schijfwereld:~/t$ ls -ltr */*
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 5/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 9/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 1/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 8/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 3/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 2/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 10/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 7/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 6/emptyfile
-rw-rw-r-- 1 rinzwind rinzwind 0 apr 16 19:57 4/emptyfile

Мой работает, но ответ Питера Кордеса лучше :)

17
ответ дан 23 April 2021 в 23:21

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

Сначала получите список каталогов с деревом .

Затем передайте их xargs следующим образом:

tree --noreport -dfi | xargs -L 1 -I {} echo touch {}/emptyfile_"$(date +%s)"

Или , в цикл while , например:

tree --noreport -dfi | \
while read -r d; do echo touch "$d"/emptyfile_"$(date +%s)"; done

Или , даже для цикла for (если имена каталогов не содержат пробелов), например:

for d in $(tree --noreport -dfi); do echo touch "$d"/emptyfile_"$(date +%s)"; done
  • echo предназначен для предотвращения непреднамеренного создания файлов во время тестирования. Если результат удовлетворительный, удалите echo , чтобы создать файлы.

  • - noreport не выводит на печать отчет о файлах и каталогах в конце списка дерева.

  • -dfi перечисляет только каталоги, печатает префикс полного пути для каждого каталога и заставляет дерево не печатать строки отступа.

  • Используйте -dfia вместо -dfi , чтобы также включить скрытые каталоги .

  • «$ (date +% s)» добавляет текущую временную метку к имени файла, как это emptyfile_1618679443 , делая его уникальным среди существующих файлов в каждом каталоге. Обратите внимание, что вы можете изменить его на случайное число, например 67639871206723 , если вам нужно фиксированное имя файла.

  • xargs -L 1 -I {} читает ввод по одной строке за раз и присваивает его {} .

3
ответ дан 23 April 2021 в 23:21
find /mountpoint -xdev -type d -exec mktemp -p {} \;

Совершенно очевидный аспект заключается в том, что вам может потребоваться или не потребоваться root-доступ для фактического создания файлов в / mountpoint .

Есть два неочевидных аспекта:

  1. Вы сказали «во всех папках файловой системы», поэтому мы начинаем с определенной / точки монтирования и не вводим другие файловые системы ( -xdev ).

    Если есть другие файловые системы, смонтированные глубже в дереве, например в / mountpoint / foo / another / mntpoint , тогда -xdev не позволит нам ввести их. Тем не менее, эти файловые системы могут маскировать целые поддеревья, принадлежащие рассматриваемой файловой системе. В лучшем случае файловая система, смонтированная в / mountpoint / foo / another / mntpoint , маскирует пустой каталог mntpoint рассматриваемой файловой системы.Таким образом, мы не можем легко добраться до «всех папок файловой системы».

    Имея root-доступ, мы можем смонтировать --bind / mountpoint /where / else заранее. С - bind (в отличие от - rbind , см. man 8 mount ) mntpoint глубоко в / где-то / else не будет копировать подмонтирование из / mountpoint / foo / another / mntpoint . Таким образом мы можем получить доступ к mntpoint , которая принадлежит рассматриваемой файловой системе.

    Этого все еще недостаточно. Если рассматриваемая файловая система - Btrfs, тогда , возможно, / точка монтирования дает доступ к некоторому подобъему, но не ко всей файловой системе (сравните этот вопрос ).

    В общем, поддерево любой (?) Смонтированной файловой системы может быть смонтировано с привязкой к другому каталогу. После того, как вы размонтируете исходную точку монтирования, другой каталог предоставит доступ к фрагменту файловой системы. Наша / точка монтирования может быть в первую очередь «другим каталогом» и, следовательно, не может предоставлять доступ ко всей файловой системе. Вы не знаете этого заранее.

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

  2. Решения с touch emptyfile или около того не обязательно «создают файл нулевого размера».Что, если интервьюер уже создал непустой пустой файл в одном из каталогов? Ловушка! Если существует непустой пустой файл , то touch не будет его создавать, и файл не будет пустым. По сути, вам не удастся «создать файл нулевого размера» в каталоге с ловушкой. По этой причине я использовал mktemp . Инструмент будет очень стараться создать новый пустой обычный файл.

7
ответ дан 23 April 2021 в 23:21

Чтобы сделать это эффективно, вы не хотите создавать новый процесс touch для каждого файла, который вы хотите создать.

Это часть того, для чего подходит xargs , разбивая аргументы на максимально большие куски, но при этом достаточно маленькие, чтобы поместиться в командной строке одного процесса. (Современный Linux имеет довольно большие ограничения, так что это уже редко проблема, xargs редко приходится на самом деле запускать вашу команду несколько раз для обработки всех аргументов, но это также позволяет вам избежать того, чтобы имя файла подвергалось разделению слов оболочки, как в foo $ (bar) .)

Мы можем использовать функцию find -printf для форматирования дополнительных материалов в каждый путь к каталогу, в частности, для нужного нам файла. xargs -0 использует байт '\ 0' в качестве разделителя, так что это безопасно с произвольными именами файлов, даже включая новую строку. Если бы вы не использовали собственный формат printf, вы могли бы просто использовать -print0 для печати путей, разделенных 0.

  find . -xdev -type d -printf '%p/empty\0'  | xargs -0 echo touch

(в тестовом каталоге, который печатает touch ./empty ./2/empty ./1/empty, а не touch ./empty, touch ./ 1 / empty и т. Д., Поэтому он запускает одно касание для нескольких файлов.)

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

  find . -xdev -type d -printf "%p/empty.$RANDOM\0"  | xargs -0 echo touch

Обратите внимание, что это одно и то же 15-битное случайное число в каждом каталоге, потому что "$ RANDOM" расширяется один раз с помощью bash перед запуском поиска. Вы можете использовать $ (дата +% s).$ RANDOM или что угодно в имени файла.


С SSD или tmpfs узким местом здесь может быть ЦП. Или, если вам повезло, и ввод-вывод метаданных на магнитном диске оказывается в основном непрерывным, потому что вы касаетесь каждого каталога (и выделяете кучу новых inodes), даже вращающийся диск может сохранить вверх несколько прилично. Хотя вы, вероятно, не касаетесь каталогов в том порядке, в котором они расположены на диске.

И тем не менее, нет необходимости тратить много времени ЦП на запуск процессов для чего-то, что должно быть ограничено вводом-выводом.


Способы, которые не работают:

  • find -exec touch {} + группирует аргументы, но -exec touch {} / empty + отказывается работать, когда {} не сам по себе.

  • xargs -I {} echo touch {} / emptyfile подразумевает -L 1 (обрабатывать только одну «строку» ввода для каждого вызова команды, будь то фактическая строка или Строка, разделенная 0, с помощью xargs -0 ). Таким образом, мы не можем использовать xargs для изменения каждого аргумента, если мы хотим использовать его для пакетной обработки аргументов.

9
ответ дан 23 April 2021 в 23:21

Другие вопросы по тегам:

Похожие вопросы: