cita dentro de backticks dentro de aspas em ksh

4

Estou tentando obter o arquivo da data atual com o seguinte comando no HP-UX Unix:

$ ls -lrt ABC.LOG* |grep "'date +"%b %d"'"

Mas, está me dando o erro:

ksh: : cannot execute
grep: can't open %d

Alguma sugestão?

    
por User123 20.08.2017 / 10:02

3 respostas

7

O erro deriva da citação dos argumentos de grep e do fato de que os backticks não fazem muito bem o aninhamento:

grep "'date +"%b %d"'"

Isto é melhor escrito como

grep "'date +'%b %d''"

... ou melhor ainda,

grep "$(date +'%b %d')"

Na verdade, com $(...) em vez de backticks, você deve conseguir manter as aspas duplas internas:

grep "$(date +"%b %d")"

Uma alternativa para mostrar a saída de ls seria fazer

find . -type f -name "ABC.LOG*" -ctime -1

Isso localizaria todos os arquivos regulares ( -type f ) no diretório atual cujos nomes correspondem ao padrão fornecido e cuja ctime é menos de 24 horas desde a hora atual . A hora do arquivo é a hora em que a última modificação dos dados ou metadados do arquivo foi feita.

Isso não é exatamente equivalente ao que você está tentando alcançar. Isso também recorre a subdiretórios.

    
por 20.08.2017 / 10:10
4

No shell Korn, como no shell Bourne, aspas e backticks (a forma arcaica de substituição de comando) podem ser incomparáveis, e você precisa ajudar o tokeniser a dizer onde os backticks terminam. Dentro dos backticks há outro nível de processamento de barra invertida.

echo "'date"

funciona e é o mesmo que:

echo "'date'"
echo "$(date)"

E:

echo 'echo "foo'

funciona e é o mesmo que:

echo 'echo "foo"'
echo $(echo "foo")

Se você fizer isso:

grep "'date +"%b %d"'"

Isso é considerado como grep word e "'date +" (backticks não-abertos entre aspas duplas) concatenado com %b e, em seguida, %d concatenado com outros backstiques não fechados entre aspas duplas: "'" . Então é como

grep "$(date +)"%b %d"$()"

(exceto que, por alguma razão, enquanto echo "''" ou echo "$()" não causaria um erro, em echo "'" , o shell tentará executar um comando com um nome vazio (como se você tivesse escrito echo "$("")" ).

Então, aqui, você precisa usar a barra invertida para ajudar o analisador:

grep "'date +\"%b %d\"'"

Essas barras invertidas são realmente removidas. É date +"%b %d" que está sendo avaliado pelo subshell na substituição do comando.

Aqui, como ksh aceita cotações não fechadas, você também pode:

grep "'date +\"%b %d"

(não que eu recomendaria fazer isso).

É também assim que você pode obter os backstacks aninhados como:

echo "'echo \"\'echo \\"a  b\\"\'\"'"

Um bom exemplo de porque ninguém raramente usa essa sintaxe e usa o formulário $(...) newer (introduzido por ksh no início dos anos 80):

echo "$(echo "$(echo "a  b")")"

Agora, para o seu problema específico, parece que você deseja listar ABC.LOG* arquivos no diretório atual que foi modificado pela última vez hoje. Para isso, você poderia fazer:

touch -t "$(date +%Y%m%d0000)" .start-of-day &&
  find . ! -name . -prune -name 'ABC.LOG.*' \
    -newer .start-of-day -type f -exec ls -lrtd {} + &&
  rm -f .start-of-day
    
por 20.08.2017 / 15:39
4

O comando find pode ser usado para a ferramenta correta, em vez de fazer ls e grep ing resultado, por isso é bom notar que por favor don't analisar ls result .

find /path/to/ -type f -name "ABC.LOG*$(date +"%b %d")*"

Acima está procurando a data de hoje em nome_do_arquivo , se você estiver procurando pelos arquivos criados / modificados na data de hoje, você pode usar find desta forma (versão GNU de find ) :

find /path/to -type f -name "ABC.LOG*" -newermt 00:00

Ou nas últimas 24 horas:

find /path/to -type f -name "ABC.LOG*" -newermt yesterday

Ou como segue:

find /path/to -type f -name "ABC.LOG*" -newermt "$(date +"%b %d")"
    
por 20.08.2017 / 11:04