Chciałbym znaleźć najnowszy podkatalog w katalogu i zapisać wynik do zmiennej w bashu.Pobierz najnowszy katalog w bashu do zmiennych
coś takiego:
ls -t /backups | head -1 > $BACKUPDIR
Czy ktoś może pomóc?
Chciałbym znaleźć najnowszy podkatalog w katalogu i zapisać wynik do zmiennej w bashu.Pobierz najnowszy katalog w bashu do zmiennych
coś takiego:
ls -t /backups | head -1 > $BACKUPDIR
Czy ktoś może pomóc?
BACKUPDIR=$(ls -t /backups | head -1)
$(...)
ocenia oświadczenie w podpowłoce i zwraca wynik.
Powyższe rozwiązanie nie uwzględnia takich rzeczy, jak zapisywane i usuwane pliki z katalogu, w wyniku czego zwracany jest katalog górny zamiast najnowszego podkatalogu.
Inną kwestią jest to, że to rozwiązanie zakłada, że katalog zawiera tylko inne katalogi, a nie zapisywane pliki.
Powiedzmy utworzyć plik o nazwie „test.txt”, a następnie ponownie uruchom polecenie:
echo "test" > test.txt
ls -t /backups | head -1
test.txt
Rezultatem jest test.txt wyświetlane zamiast ostatniego zmodyfikowanego katalogu.
Proponowane rozwiązanie "działa", ale tylko w najlepszym przypadku.
zakładając, że masz maksymalnie 1 głębokości katalogów, lepszym rozwiązaniem jest użycie:
find /backups/* -type d -prune -exec ls -d {} \; |tail -1
Wystarczy zamienić „/ backups /” część dla aktualnej ścieżki.
Jeśli chcesz uniknąć wyświetlania bezwzględną ścieżkę w skrypcie bash, zawsze można użyć czegoś takiego:
LOCALPATH=/backups
DIRECTORY=$(cd $LOCALPATH; find * -type d -prune -exec ls -d {} \; |tail -1)
Pomimo przegranych, to rozwiązanie nie działa. 'find/backups/* -type d -prune -exec ...' przetwarza katalogi w kolejności, w jakiej są tworzone, gdy powłoka rozszerzy '/ backups/*'. Kolejność określają nazwy, a nie znaczniki czasu. Ostatni z wymienionych katalogów będzie normalnie _nie_ być najnowszym. – pjh
Aby uzyskać najnowszy folder używając ls -t
może trzeba odróżnić pliki z folderów, jeśli katalog nie ma tylko katalogów. Stosując prostą pętlę trzeba będzie bezpieczny i szybki rezultat, a także pozwala na łatwe wdrożenie różnych filtrów w przyszłości:
while read i ; do if [ -d "${i}" ] ; then newestFolder="${i}" ; break ; fi ; done < <(ls -t)
opracowano blok:
while read currentItemOnLoop # While reading each line of the file
do
if [ -d "${currentItemOnLoop}" ] # If the item is a folder
then
newestFolder="${currentItemOnLoop}" # Then save it into the "newestFolder" variable
break # and stop the loop
else
continue # Look for the next newest item
fi
done < <(ls -t) # Sending the result of "ls -t" as a "file" to the "while read" loop
Strzeż logiki continue
na moim opracowanego bloku :
else
continue # Look for the next newest item
Nie użyjesz go. Umieściłem to tylko ze względu na twoją widoczność, ponieważ w tym przypadku nie wpłynęłoby to na wyniki.
Cóż, myślę, że jest to rozwiązanie najbardziej efektywne:
path="/my/dir/structure/*"
backupdir=$(find $path -type d -prune | tail -n 1)
Wyjaśnienie, dlaczego to jest trochę lepiej:
Nie potrzebujemy sub-muszle (oprócz jednego uzyskania wyniku do zmiennej bash). Nie potrzebujemy niepotrzebnego -exec ls -d
na końcu polecenia find
, już wypisuje listing katalogu. Możemy łatwo to zmienić, np. aby wykluczyć pewne wzorce. Na przykład, jeśli chcesz sekund najnowszego katalogu, ponieważ pliki kopii zapasowych są najpierw zapisywane w tmp dir w tej samej ścieżce:
backupdir=$(find $path -type -d -prune -not -name "*temp_dir" | tail -n 1)
Dla mnie to nie zamawianie folderów. – pfnuesel
Ten ia czystego roztworu bash
topdir=/backups
BACKUPDIR=
# Handle subdirectories beginning with '.', and empty $topdir
shopt -s dotglob nullglob
for file in "$topdir"/* ; do
[[ -L $file || ! -d $file ]] && continue
[[ -z $BACKUPDIR || $file -nt $BACKUPDIR ]] && BACKUPDIR=$file
done
printf 'BACKUPDIR=%q\n' "$BACKUPDIR"
pomija dowiązania , w tym dowiązania symboliczne do katalogów, które mogą być lub nie są właściwe. Pomija inne nie-katalogi. Obsługuje katalogi, których nazwy zawierają dowolne znaki, w tym znaki nowej linii i kropki wiodące.
Istnieje proste rozwiązanie tego używając tylko ls
:
BACKUPDIR=$(ls -td /backups/*/ | head -1)
-t
zamówień według czasu (najpierw najnowsze)-d
wymienia tylko elementy z tego folderu*/
tylko wymienia katalogihead -1
zwraca pierwszy elementNie wiedziałem o */
, dopóki nie znalazłem Listing only directories using ls in bash: An examination.
W odpowiedzi na komentarz pjh dotyczący zaakceptowanej odpowiedzi "Nie działa, jeśli najnowszy katalog zaczyna się od". "", Co również odnosi się do mojej odpowiedzi. Jeśli chcesz uwzględnić foldery zaczynające się od. (ale wykluczyć ./ i ../) można zmienić ls na: ls -td /backups/{.[^.],}?*/ – Martin
Mimo akceptacji i znacznej przewartościowania istnieje kilka problemów z tym rozwiązaniem. Nie działa, jeśli najnowszy element w katalogu nie jest katalogiem. Nie działa, jeśli najnowszy podkatalog ma nazwę zaczynającą się od ".". Nie działa, jeśli najnowszy podkatalog ma nazwę zawierającą znak nowej linii. [Shellcheck] (http://www.shellcheck.net/) narzeka na użycie 'ls'. Zobacz [ParsingLs - Greg's Wiki] (http://mywiki.wooledge.org/ParsingLs), aby uzyskać szczegółowe wyjaśnienie niebezpieczeństw związanych z przetwarzaniem danych wyjściowych 'ls'. – pjh