Недавно на собеседовании меня спросили," как создать файл нулевого размера [I Думаете, это означает пустой файл] во всех папках файловой системы? "
Я нашел вопрос немного странным, я подумал о цикле, чтобы перечислить все каталоги и использовать touch
или возможно, перейдите в корневой каталог и используйте коснитесь
с рекурсивной опцией. У вас есть идеи?
Это может быть ...
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
Мой работает, но ответ Питера Кордеса лучше :)
Это создаст пустой файл с уникальным именем в каждом каталоге , начиная с и по убыванию от текущего каталога. включая скрытых каталогов , если хотите.
Сначала получите список каталогов с деревом
.
Затем передайте их 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 {}
читает ввод по одной строке за раз и присваивает его {}
.
find /mountpoint -xdev -type d -exec mktemp -p {} \;
Совершенно очевидный аспект заключается в том, что вам может потребоваться или не потребоваться root-доступ для фактического создания файлов в / mountpoint
.
Есть два неочевидных аспекта:
Вы сказали «во всех папках файловой системы», поэтому мы начинаем с определенной / точки монтирования
и не вводим другие файловые системы ( -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…
, указанную в начале этого ответа.
Решения с touch emptyfile
или около того не обязательно «создают файл нулевого размера».Что, если интервьюер уже создал непустой пустой файл
в одном из каталогов? Ловушка! Если существует непустой пустой файл
, то touch
не будет его создавать, и файл не будет пустым. По сути, вам не удастся «создать файл нулевого размера» в каталоге с ловушкой. По этой причине я использовал mktemp
. Инструмент будет очень стараться создать новый пустой обычный файл.
Чтобы сделать это эффективно, вы не хотите создавать новый процесс 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 для изменения каждого аргумента, если мы хотим использовать его для пакетной обработки аргументов.