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 xargsil -rflag lo farà funzionare solo basenamese 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 lsil 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_DIRcontiene 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 basenamefunziona.
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 xargssignificherebbe 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 zshsenza 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_namearray 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 lscomando in questione sta cercando il file più vecchio in una directory. questa stessa funzione potrebbe essere rinominata oldeste avere [[ $file -ot $oldest ]] && oldest=$fileinvece 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.
lsapprocci basati su, se ci sono collegamenti simbolici, verrà considerato il tempo di modifica della destinazione dei collegamenti simbolici (aggiungere l' -Lopzione lsper 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.
lsnon fallirà.