Kombinace find
a ls
funguje dobře pro
- názvy souborů bez nových řádků
- nepříliš velké množství souborů
- nepříliš dlouhé názvy souborů
Řešení:
find . -name "my-pattern" -print0 |
xargs -r -0 ls -1 -t |
head -1
Pojďme to rozebrat:
S find
můžeme spárovat všechny zajímavé soubory takto:
find . -name "my-pattern" ...
poté pomocí -print0
můžeme všechny názvy souborů bezpečně předat do ls
takhle:
find . -name "my-pattern" -print0 | xargs -r -0 ls -1 -t
další find
parametry vyhledávání a vzory lze přidat zde
find . -name "my-pattern" ... -print0 | xargs -r -0 ls -1 -t
ls -t
seřadí soubory podle času úpravy (nejnovější jako první) a vytiskne je jeden na řádku. Můžete použít -c
seřadit podle času vytvoření. Poznámka :toto přeruší názvy souborů obsahujících nové řádky.
Nakonec head -1
dostane první soubor v seřazeném seznamu.
Poznámka: xargs
použijte systémové limity velikosti seznamu argumentů. Pokud tato velikost překročí, xargs
zavolá ls
vícekrát. Tím se rozbije řazení a pravděpodobně i konečný výstup. Spustit
xargs --show-limits
zkontrolovat limity vašeho systému.
Poznámka 2: použijte find . -maxdepth 1 -name "my-pattern" -print0
pokud nechcete prohledávat soubory v podsložkách.
Poznámka 3: Jak zdůraznil @starfry - -r
argument pro xargs
brání volání ls -1 -t
, pokud žádné soubory neodpovídají find
. Děkujeme za návrh.
ls
příkaz má parametr -t
seřadit podle času. Pak můžete získat první (nejnovější) s head -1
.
ls -t b2* | head -1
Ale pozor:Proč byste neměli analyzovat výstup ls
Můj osobní názor:parsování ls
je nebezpečné pouze tehdy, když názvy souborů mohou obsahovat zábavné znaky, jako jsou mezery nebo nové řádky. Pokud můžete zaručit, že názvy souborů nebudou obsahovat vtipné znaky, pak analyzujte ls
je docela bezpečný.
Pokud vyvíjíte skript, který má být spouštěn mnoha lidmi na mnoha systémech v mnoha různých situacích, pak velmi doporučuji neanalyzovat ls
.
Zde je návod, jak to udělat „správně“:Jak najdu nejnovější (nejnovější, nejstarší, nejstarší) soubor v adresáři?
unset -v latest
for file in "$dir"/*; do
[[ $file -nt $latest ]] && latest=$file
done
Toto je možná implementace požadované funkce Bash:
# Print the newest file, if any, matching the given pattern
# Example usage:
# newest_matching_file 'b2*'
# WARNING: Files whose names begin with a dot will not be checked
function newest_matching_file
{
# Use ${1-} instead of $1 in case 'nounset' is set
local -r glob_pattern=${1-}
if (( $# != 1 )) ; then
echo 'usage: newest_matching_file GLOB_PATTERN' >&2
return 1
fi
# To avoid printing garbage if no files match the pattern, set
# 'nullglob' if necessary
local -i need_to_unset_nullglob=0
if [[ ":$BASHOPTS:" != *:nullglob:* ]] ; then
shopt -s nullglob
need_to_unset_nullglob=1
fi
newest_file=
for file in $glob_pattern ; do
[[ -z $newest_file || $file -nt $newest_file ]] \
&& newest_file=$file
done
# To avoid unexpected behaviour elsewhere, unset nullglob if it was
# set by this function
(( need_to_unset_nullglob )) && shopt -u nullglob
# Use printf instead of echo in case the file name begins with '-'
[[ -n $newest_file ]] && printf '%s\n' "$newest_file"
return 0
}
Používá pouze vestavěné moduly Bash a měl by zpracovávat soubory, jejichž názvy obsahují nové řádky nebo jiné neobvyklé znaky.