Как мне сказать mkdir попытаться создать dir1, и если он уже существует, создать dir2 и т. Д., Пока он не найдет имя, которое не существует?

13

Я хочу создать каталог с номером в конце, например, «dir1», и увеличивать его, если каталог уже существует, пока не найдет имя каталога, которого не существует, и мне нужно сделать это в одной строке в командная строка Linux, что-то вроде:

mkdir --increment dir$

Как бы я поступил так?

Пока у меня есть это:

dir=output; n=0; mkdir -p $dir$n; if test -d $dir$n; then n=$((n+1)); echo $dir$n; fi

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

01AutoMonkey
источник

Ответы:

26

Это тривиальное упражнение в использовании while:

п = 0
пока ! mkdir dir $ n
делать
    п = $ ((п + 1))
сделано

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

Таким образом, вместо того, чтобы заново изобретать колесо и снова сбрить все углы, можно создать уникальные временные каталоги из шаблона немного по-другому:

имя = $ (mktemp -d dirXXXXXXXXXXX)

JdeBP
источник
Двоичный поиск по номеру может быть достаточно хорошим.
Турбьёрн Равн Андерсен
Есть немало углов, с которых вы можете начать свою работу в процессе переосмысления колеса, и не в последнюю очередь вспомните о файловой системе, учитывая безопасность и распараллеливание.
JdeBP
6

Если вы просто хотите постепенно создавать каталоги, которые перечислены в правильном порядке, могу ли я вместо этого рекомендовать папки с именами на основе текущей даты?

DATE=$(date +%F)
mkdir "dir-$DATE"

Он создаст каталоги с такими именами dir-2014-03-02( YYYY-MM-DDчтобы они отображались в алфавитном порядке).

Если вы создаете более одного каталога в день, вы можете добавить текущее время к имени файла. Смотрите man dateкак настроить выходное форматирование date.

IQAndreas
источник
5

сначала найдите «самый большой» dirname, получите число и увеличьте его:

last_dir=(printf "%s\n" dir* | sort -Vr | head -1)
num=$(last_dir#dir)
mkdir "dir$((num+1))"
Гленн Джекман
источник
Это хорошая идея, но ее нелегко парализовать.
Турбьёрн Равн Андерсен
Если нет миллионов каталогов, распараллеливание определенно преждевременная оптимизация.
Гленн Джекман
Зачем вам printfздесь? Не будет простой echoработы?
Руслан
Кроме того, я бы использовал dir[0-9]*вместо dir*.
Руслан
1
Ты не понимаешь. Я говорю о том, целесообразно ли запускать скрипт несколько раз одновременно (несколько потоков, несколько пользователей и т. Д.) Или нет.
Турбьёрн Равн Андерсен
2

Предполагая, что ваши каталоги всегда начинаются с "dir1", и что нет файлов с именем $ dir * (т. Е. Все они являются последовательно пронумерованными каталогами), вы можете избежать неприятностей с этим одним вкладышем -

mkdir ${dir}$(( `ls ${dir}* | wc -w` + 1 ))

Это подсчитывает количество файлов, начинающихся с $ dir, затем добавляет один к этому числу и создает новый файл.

davidgo
источник
0

Приложение к другим ответам: Если вам нужно, чтобы каталоги правильно сортировались по имени, вы также можете дополнить новый номер каталога (NUM) начальными нулями до фиксированной длины.

Следующее может быть сжато в одну строку или встроено в одно из других решений.

NUM="00"$NUM                  ## Left zero pad with fixed length - 1 zeros 
NUM=${NUM:((${#NUM} - 3)):3}  ## left trim to fixed length (3 in this case)

Это предполагает, что NUM начинается с длиной не менее 1 цифры и не будет превышать фиксированную длину. Отрегулируйте в соответствии с вашими требованиями.

Джо
источник