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

4646
01AutoMonkey

Я хочу создать каталог с номером в конце, например, «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 

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

13

5 ответов на вопрос

26
JdeBP

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

п = 0 в то время как ! mkdir dir $ n делать п = $ ((п + 1)) сделанный

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

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

имя = $ (mktemp -d dirXXXXXXXXXXX)

Двоичный поиск по номеру может быть достаточно хорошим. Thorbjørn Ravn Andersen 10 лет назад 0
Есть немало углов, с которых можно начать свою работу в процессе переосмысления колеса, не в последнюю очередь из которых вспоминается файловая система, учитывается безопасность и распараллеливание. JdeBP 10 лет назад 0
5
glenn jackman

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

last_dir=(printf "%s\n" dir* | sort -Vr | head -1) num=$(last_dir#dir) mkdir "dir$((num+1))" 
Это хорошая идея, но ее нелегко парализовать. Thorbjørn Ravn Andersen 10 лет назад 0
Если нет миллионов каталогов, распараллеливание определенно преждевременная оптимизация. glenn jackman 10 лет назад 0
Зачем вам здесь `printf`? Разве простое `эхо` не сработает? Ruslan 10 лет назад 0
Кроме того, я бы использовал `dir [0-9] *` вместо `dir *`. Ruslan 10 лет назад 0
Ты не понимаешь. Я говорю о том, целесообразно ли запускать скрипт несколько раз одновременно (несколько потоков, несколько пользователей и т. Д.) Или нет. Thorbjørn Ravn Andersen 10 лет назад 1
@Ruslan, для сортировки требуется одно имя файла на строку. echo просто выведет имена файлов через пробел. Обратите внимание, что `dir [0-9] *` будет по-прежнему соответствовать "dir1a". Для «dir, за которым следуют числа» мы можем сделать: `shopt -s extglob; printf "% s \ n" dir + ([0-9]) ` glenn jackman 10 лет назад 0
4
IQAndreas

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

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

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

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

2
davidgo

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

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

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

0
Joe

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

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

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

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

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