INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Volevo eseguire il secondo comando ( head -1
) solo se il primo comando ha esito positivo. Come posso migliorare questo comando?
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Volevo eseguire il secondo comando ( head -1
) solo se il primo comando ha esito positivo. Come posso migliorare questo comando?
Risposte:
Prova questo:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
Passare xargs
il -r
flag lo farà funzionare solo basename
se legge almeno un elemento dallo standard input ( head -1
).
head -1
verrà eseguito ma non vedrai né catturerai alcun output da esso.
Inoltre, se non si desidera che l'utente visualizzi alcun output degli errori ls
, è possibile reindirizzare ls
il flusso stderr a /dev/null
.
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`
Si noti inoltre che ho aggiunto virgolette in giro $MY_DIR
. In questo modo, il comando non fallirà se $MY_DIR
contiene spazi.
Se stai usando una shell moderna come bash, dovresti usare una $( )
shell di cattura invece di backtick. Dovresti anche considerare di cambiare lo stile delle tue variabili. Dovresti generalmente evitare di usare nomi di variabili maiuscoli negli script. Tale stile è generalmente riservato a variabili riservate e ambientali.
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename)
ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basename
funziona.
In una linea di condotte, tutti i comandi vengono avviati ed eseguiti contemporaneamente, non uno dopo l'altro. Quindi è necessario memorizzare l'output da qualche parte.
if ls_output=$(ls -rtd -- "$MY_DIR"/FILE.*.xml); then
first_file=$(printf '%s\n' "$ls_output" | head -n 1)
first_file_name=$(basename -- "$first_file")
fi
Si noti che presuppone che i nomi dei file non contengano caratteri di nuova riga. L'uso xargs
significherebbe anche problemi con caratteri vuoti, virgolette singole e doppie e barre rovesciate. Lasciare le variabili non quotate significherebbe problemi con spazi, tab e caratteri jolly. Dimenticare --
significherebbe problemi con i nomi dei file a partire da -
.
Per ottenere il nome di base del file più vecchio zsh
senza nessuna di quelle restrizioni sui caratteri (evita anche il problema della dimensione limitata degli argomenti di un comando):
first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
Se non c'è corrispondenza, quel comando fallirà e interromperà lo script. Puoi anche fare:
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
Nel qual caso l' first_file_name
array conterrà 1 elemento in caso di corrispondenza o 0 in caso contrario. È quindi possibile fare:
if (($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2 No match
fi
Trova l'ultimo file modificato in una directory:
latest() {
local file path=${1:-.} ext=${2-} latest
for file in "${path%/}"/*"$ext"; do
[[ $file -nt $latest ]] && latest=$file
done
[[ $latest ]] && printf '%s\n' "$latest"
}
Uso: latest [directory/path/ [.extension]]
Invece di chiamare basename
, utilizzare l'espansione dei parametri.
in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}
In una directory con questi contenuti:
foo.xml bar.xml baz.xml newest.xml
Il contenuto della variabile base_fn sarebbe: newest
Per utilizzarlo correttamente per soddisfare lo scopo della tua richiesta:
check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir" "$check_ext"); then
base_fn=${in_file##*/} base_fn=${base_fn%.*}
else
printf '%s\n' "No file found in $check_dir" >&2
fi
EDIT: dopo aver esaminato la domanda, mi sono reso conto che il ls
comando in questione sta cercando il file più vecchio in una directory. questa stessa funzione potrebbe essere rinominata oldest
e avere [[ $file -ot $oldest ]] && oldest=$file
invece per ottenere lo stesso effetto. scuse per qualsiasi confusione.
la cosa importante da notare è che tu, assolutamente in nessun caso nell'umanità, non dovresti analizzare l'output di ls. mai.
ls
approcci basati su, se ci sono collegamenti simbolici, verrà considerato il tempo di modifica della destinazione dei collegamenti simbolici (aggiungere l' -L
opzione ls
per ottenere lo stesso comportamento lì).
Penso che l'opzione migliore qui sia:
ls -rf $MY_DIR/FILE.*.xml
if [ $? -eq 0 ]; then
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml|head -1|xargs basename `
else
echo "Error!"
fi
se non è presente alcun file, il codice di ritorno di ls è 2 ma se trova un file sarà 0.
ls
non fallirà.