INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Eu queria executar o segundo comando ( head -1
) apenas se o primeiro comando for bem-sucedido. Como melhoro este comando?
INPUT_FILE=`ls -rt $MY_DIR/FILE.*.xml | head -1 | xargs basename`
Eu queria executar o segundo comando ( head -1
) apenas se o primeiro comando for bem-sucedido. Como melhoro este comando?
Respostas:
Tente o seguinte:
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml | head -1 | xargs -r basename`
Passar xargs
o -r
sinalizador fará com que ele seja executado apenas basename
se ler pelo menos um item da entrada padrão (head -1
).
head -1
será executado, mas você não verá nem capturará nenhuma saída dele.
Além disso, se você não quiser que o usuário veja nenhuma saída de erro ls
, poderá redirecionar ls
o fluxo stderr para /dev/null
.
INPUT_FILE=`ls -rt "$MY_DIR"/FILE.*.xml 2> /dev/null | head -1 | xargs -r basename`
Observe também que adicionei aspas $MY_DIR
. Dessa forma, o comando não falhará se $MY_DIR
contiver espaços.
Se você estiver usando um shell moderno como o bash, use um $( )
shell de captura em vez de backticks. Você também deve mudar o estilo de suas variáveis. Geralmente, você deve evitar o uso de nomes de variáveis com todas as letras maiúsculas nos scripts. Esse estilo geralmente é reservado para variáveis reservadas e ambientais.
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
funciona.
Em uma linha de tubulação, todos os comandos são iniciados e executados simultaneamente, não um após o outro. Então você precisa armazenar a saída em algum lugar.
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
Observe que ele assume que os nomes dos arquivos não contêm caracteres de nova linha. O uso xargs
também significaria problemas com caracteres em branco, aspas simples e duplas e barras invertidas. Deixar as variáveis sem aspas significaria problemas com caracteres de espaço, tabulação e curinga. Esquecer --
significaria problemas com nomes de arquivos começando com -
.
Para obter o nome de base do arquivo mais antigo zsh
sem nenhuma dessas restrições de caracteres (também evita o problema do tamanho limitado dos argumentos de um comando):
first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
Se não houver correspondência, esse comando falhará e abortará o script. Você também pode fazer:
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
Nesse caso, o first_file_name
matriz conterá 1 elemento, se houver uma correspondência, ou 0, se não houver. Você pode então fazer:
if (($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2 No match
fi
Encontre o arquivo modificado mais recente em um diretório:
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]]
Em vez de chamar basename
, use expansão de parâmetro.
in_file=$(latest in/my/dir .xml)
base_fn=${in_file##*/} base_fn=${base_fn%.*}
Em um diretório com este conteúdo:
foo.xml bar.xml baz.xml newest.xml
O conteúdo da variável base_fn seria: newest
Para usá-lo corretamente para servir ao propósito de sua solicitação:
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: após a revisão da questão, percebi que o ls
comando em questão está procurando o arquivo mais antigo em um diretório. essa mesma função pode ser renomeada paraoldest
e ter[[ $file -ot $oldest ]] && oldest=$file
o mesmo efeito. desculpas por qualquer confusão.
o importante a ser observado é que você absolutamente, sob nenhuma circunstância jamais na humanidade, deve analisar a produção de ls. Nunca.
ls
abordagens baseadas em, se houver links simbólicos, o tempo de modificação do destino dos links simbólicos será considerado (adicione a -L
opção ls
para obter o mesmo comportamento).
Eu acho que a melhor opção aqui é:
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 não houver arquivo, o código de retorno de ls será 2, mas se encontrar algum arquivo será 0.
ls
não falhará.