Jak powiedzieć mkdir, aby spróbował utworzyć katalog 1, a jeśli już istnieje, utwórz katalog 2 itd., Dopóki nie trafi na nazwę, która nie istnieje?

13

Chcę utworzyć katalog z numerem na końcu, na przykład „dir1”, i zwiększyć ten numer, jeśli katalog już istnieje, dopóki nie trafi na nazwę katalogu, który nie istnieje, i muszę to zrobić w jednym wierszu w wiersz poleceń Linuksa, coś w stylu:

mkdir --increment dir$

Jak miałbym to zrobić?

Do tej pory mam to:

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

Ale to tylko echo następnej nazwy katalogu, potrzebuję go, aby rekurencyjnie wykonać polecenie.

01AutoMonkey
źródło

Odpowiedzi:

26

Jest to trywialne ćwiczenie z wykorzystaniem while:

n = 0
podczas ! mkdir reż. $ n
robić
    n = $ ((n + 1))
gotowy

Ale oczywiście nie trzeba wiele myśleć o tym, że ten trywialny mechanizm nie skaluje się dobrze.

Zamiast więc na nowo wymyślać koło i ponownie musieć golić wszystkie rogi, tworzy się unikalne katalogi tymczasowe z szablonu nieco inaczej:

name = $ (mktemp -d dirXXXXXXXXXXX)

JdeBP
źródło
Wyszukiwanie binarne liczby może być wystarczające.
Thorbjørn Ravn Andersen
Jest wiele zakątków, z których należy się wystartować od miejsca, w którym zaczynasz proces ponownego wymyślania koła, z których przynajmniej pamiętasz system plików, biorąc pod uwagę bezpieczeństwo i równoległość.
JdeBP
6

Jeśli chcesz tylko stopniowo tworzyć katalogi wymienione we właściwej kolejności, czy zamiast tego mogę polecić foldery o nazwach opartych na bieżącej dacie?

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

Stworzy katalogi o nazwach takich jak dir-2014-03-02( YYYY-MM-DD, aby pojawiały się w kolejności alfabetycznej).

Jeśli tworzysz więcej niż jeden katalog dziennie, możesz dodać bieżący czas do nazwy pliku. Zobacz, man datejak dostosować formatowanie wyjściowe date.

IQAndreas
źródło
5

najpierw znajdź „największą” nazwę katalogu, uzyskaj liczbę i przyrost, który:

last_dir=(printf "%s\n" dir* | sort -Vr | head -1)
num=$(last_dir#dir)
mkdir "dir$((num+1))"
Glenn Jackman
źródło
To dobry pomysł, ale niełatwo go sparaliżować.
Thorbjørn Ravn Andersen
Jeśli nie ma milionów katalogów, równoległość jest zdecydowanie przedwczesną optymalizacją.
glenn jackman
Dlaczego miałbyś printftu potrzebować ? Czy prosta echopraca nie będzie ?
Ruslan
Również użyłbym dir[0-9]*zamiast dir*.
Ruslan
1
Nie zrozumiałeś. Mówię o tym, czy skrypt może być uruchamiany wiele razy jednocześnie (wiele wątków, wielu użytkowników itp.).
Thorbjørn Ravn Andersen
2

Zakładając, że twoje katalogi zawsze zaczynają się od „dir1” i że nie ma żadnych plików o nazwie $ dir * (tzn. Wszystkie są katalogami o numerach sekwencyjnych), możesz uciec od tego jednego linijki -

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

Zlicza liczbę plików zaczynających się od $ dir, a następnie dodaje jeden do tej liczby i tworzy nowy plik.

Davidgo
źródło
0

Dodatek do innych odpowiedzi: Jeśli potrzebujesz katalogów, aby posortować poprawnie według nazwy, możesz również wprowadzić nowy numer katalogu (NUM) z zerami wiodącymi do stałej długości.

Następujące elementy można skondensować w jednej linii lub osadzić w jednym z pozostałych rozwiązań.

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)

Zakłada się, że NUM zaczyna się od co najmniej 1 cyfry i nie przekroczy ustalonej długości. Dostosuj odpowiednio do swoich wymagań.

Joe
źródło