Как мне сказать 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

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

Ответы:


26

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

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

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

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

имя = $ (mktemp -d dirXXXXXXXXXXX)


Двоичный поиск по номеру может быть достаточно хорошим.
Турбьёрн Равн Андерсен

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

6

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

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

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

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


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, затем добавляет один к этому числу и создает новый файл.


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 цифры и не будет превышать фиксированную длину. Отрегулируйте в соответствии с вашими требованиями.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.