Como escolher o arquivo mais antigo em uma pasta do diretório [duplicado]

0

Eu tinha n número de arquivos no meu diretório ../in/ . A partir desses arquivos, quero que o arquivo mais antigo seja processado e enviá-lo para o diretório ../complete/ . Os arquivos restantes são enviados para o diretório ../error/ . Alguém pode ajudar?

    
por Sreeni 24.06.2016 / 07:11

3 respostas

1

Para copiar o arquivo mais antigo para ../complete :

cp -v "$(find ../in -maxdepth 1 -type f -printf '%T@ %p
find ../in -maxdepth 1 -type f -printf '%T@ %p
$ ls -lt ../in/
total 0
-rw-r--r-- 1 user user 0 Jun 24 08:18 file2
-rw-r--r-- 1 user user 0 Jun 24 08:18 file3
-rw-r--r-- 1 user user 0 Jun 24 08:18 file4
-rw-r--r-- 1 user user 0 Jun 24 08:18 file5
-rw-r--r-- 1 user user 0 Jun 24 08:17 file_oldest
$ cp -v "$(...)" ../complete
'../in/file_oldest' -> '../complete/file_oldest'
$
$ find ... | xargs ... ../error
'../in/file2' -> '../error/file2'
'../in/file3' -> '../error/file3'
'../in/file4' -> '../error/file4'
'../in/file5' -> '../error/file5'
' | sort -zn | \ sed -zn '2,$s/[0-9,\.]\+ //p' | xargs -0 cp -vt ../error
' | sort -zn | \ sed -zn '1s/[0-9,\.]\+ //p')" ../complete

Para copiar o todo, exceto o mais antigo para ../error :

cp -v "$(find ../in -maxdepth 1 -type f -printf '%T@ %p
find ../in -maxdepth 1 -type f -printf '%T@ %p
$ ls -lt ../in/
total 0
-rw-r--r-- 1 user user 0 Jun 24 08:18 file2
-rw-r--r-- 1 user user 0 Jun 24 08:18 file3
-rw-r--r-- 1 user user 0 Jun 24 08:18 file4
-rw-r--r-- 1 user user 0 Jun 24 08:18 file5
-rw-r--r-- 1 user user 0 Jun 24 08:17 file_oldest
$ cp -v "$(...)" ../complete
'../in/file_oldest' -> '../complete/file_oldest'
$
$ find ... | xargs ... ../error
'../in/file2' -> '../error/file2'
'../in/file3' -> '../error/file3'
'../in/file4' -> '../error/file4'
'../in/file5' -> '../error/file5'
' | sort -zn | \ sed -zn '2,$s/[0-9,\.]\+ //p' | xargs -0 cp -vt ../error
' | sort -zn | \ sed -zn '1s/[0-9,\.]\+ //p')" ../complete

Explicação :

  • %código%
    • find desce apenas 1 nível; portanto, ele não pesquisará o diretório negativamente.
    • -maxdepth 1 corresponde apenas a arquivos.
    • -type f um formato de saída personalizado. -printf '...' fornece a hora da última modificação do arquivo em um registro de data e hora, %T@ é o nome do arquivo. Observe o %p no final. Os arquivos são impressos delimitados por byte nulo, não delimitados por nova linha, porque a nova linha provavelmente poderia ser um caractere no nome do arquivo, o que quebraria o comando.
  • sort -zn lerá a saída delimitada por byte nulo ( -z ) e classificará numericamente ( -n ).
  • sed -zn lê a saída delimitada por byte nulo.
    • 1 corresponderá apenas à primeira linha (primeiro comando) e 2,$ corresponderá a todos os outros (segundo comando)
    • s/[0-9,\.]\+ //p removerá o timestamp principal da saída.
  • Apenas do segundo comando: xargs -0 cp -vt ../error processa a saída delimitada por byte nulo ( -0 ) e chama cp -vt ../error em toda entrada, que copia os arquivos.

Exemplo de saída :

%pre%     
por 24.06.2016 / 08:19
1

Para encontrar o arquivo mais antigo e movê-lo para o diretório desejado, use:

# cd to ../in/

$ ls -lt | grep -v '^d' | tail -1 | awk '{print $NF}' | xargs -I '{}' mv '{}' ../complete/

Agora que seu arquivo mais antigo foi removido, você pode mover todos os arquivos para ../error/

$ mv -- * ../error/

O -- após mv é necessário se você tiver qualquer nome de arquivo / diretório que comece com - .

    
por 24.06.2016 / 07:36
1

Aproveitando a resposta da Rahul :

$ ls -ltr | grep -v '^d' | awk 'NR==2 {print $NF; exit}' | xargs -I '{}' mv -- '{}' ../complete/

Notas:

  • Você diz que quer fazer algo com "o arquivo mais antigo". Todas as respostas estão assumindo que você quer dizer menos recentemente modificado. Se você quer dizer menos recentemente mudou , diga isso; as respostas serão ligeiramente diferentes. Se você quer dizer menos recentemente criado , o que você quer é quase impossível no Unix.
  • ls -lt (o que o Rahul usou) lista o diretório atual em formato longo, por ordem de data / hora de modificação, com o mais novo primeiro e o mais antigo por último. ls -ltr é o r everse disso; o mais antigo primeiro e o mais novo por último.
  • Se você tiver arquivos cujos nomes começam com um ponto ( . ), adicione a opção A a ls ; por exemplo, ls -ltrA . (A ordem das opções não importa; você pode usar ls -ltAr , ls -lAtr ou mesmo ls -ltr -A se quiser.)
  • eu menti. Uma longa lista de ls de um diretório sempre tem uma linha total primeiro. Em ls -ltr , a entrada mais antiga está na linha segundo .
  • grep -v '^d' filtra os diretórios (se houver).
  • awk 'NR==2 { print $NF; exit }' imprime o último campo (o nome do arquivo *) da segunda linha (o arquivo mais antigo) e depois sai.

    • Este é um processo a menos que tail -1 | awk '{print $NF}' .
    • Isso pode funcionar mais rápido porque, quando o awk sai, o ls também pode sair, e você evitaria gerar a listagem para o diretório inteiro.
    • Você pode eliminar o grep fazendo

      ls -ltr | awk '! /^d/ { count++ } count==2 { print $NF; exit }'
      

      mas eu não aconselho. Scripts excessivamente complexos são difíceis de manter.

  • O -- após mv no comando xargs é necessário se você tiver algum nome de arquivo que comece com - .
  • Você realmente não precisa do xargs . Você pode simplificar o comando acima para

    $ mv -- $(ls -ltr | grep -v '^d' | awk 'NR==2 { print $NF; exit }') ../complete/
    

por 24.06.2016 / 10:16