Mover um arquivo baseado em seu conteúdo

2

Um diretório recebe muitos arquivos ao longo do dia. Eu só quero selecionar e mover os arquivos de acordo com o conteúdo da linha 2. Aqui está o que linha 2 parece:

L054   EL621306DEM-A0-AGI378-0001  70807 201708072017081100061542364673600268
  • Condição 1: colunas 8 e amp; 9 = EL
  • Condição 2: colunas 42/43/44/45 = 2017

(usando ksh no AIX 7.1)

    
por Kiko Netzone 08.08.2017 / 12:46

1 resposta

2

Com ferramentas GNU (shell GNU ou outro shell com suporte para ksh substituição de processo ( <(...) ), GNU xargs ou compatível como o FreeBSD (para -a , -r , -0 ), GNU mv para -t , GNU awk para nextfile (também suportado por algumas outras implementações; ele será ignorado, mas menos eficiente quando não suportado)):

xargs -r0a <(
  find dir -type f -exec awk 'FNR == 2 {
    if (substr($0, 8, 2) == "EL" && substr($0, 42, 4) == "2017")
      printf "%s
{
find dir -type f -exec awk -v q="'" '
  function quote_for_xargs(s) {
    gsub(q, q "\" q q, s)
    gsub("\n", q "\\n" q, s)
    return q s q
  }
  FNR == 2 {
    if (substr($0, 8, 2) == "EL" && substr($0, 42, 4) == "2017")
      print quote_for_xargs(FILENAME)
    nextfile
  }' {} + | xargs sh -c '
  [ "$#" -eq 0 ] || exec echo mv -i "$@" /somewhere <&3 3<&-' sh
} 3<&0
", FILENAME nextfile}' {} +) echo mv -it /somewhere

(remova echo se estiver feliz)

Em sistemas não-GNU, você pode alterá-lo para:

xargs -r0a <(
  find dir -type f -exec awk 'FNR == 2 {
    if (substr($0, 8, 2) == "EL" && substr($0, 42, 4) == "2017")
      printf "%s
{
find dir -type f -exec awk -v q="'" '
  function quote_for_xargs(s) {
    gsub(q, q "\" q q, s)
    gsub("\n", q "\\n" q, s)
    return q s q
  }
  FNR == 2 {
    if (substr($0, 8, 2) == "EL" && substr($0, 42, 4) == "2017")
      print quote_for_xargs(FILENAME)
    nextfile
  }' {} + | xargs sh -c '
  [ "$#" -eq 0 ] || exec echo mv -i "$@" /somewhere <&3 3<&-' sh
} 3<&0
", FILENAME nextfile}' {} +) echo mv -it /somewhere

(remova echo se estiver feliz).

Isso tem find call awk para cada arquivo de texto. Em awk , para a segunda linha de cada arquivo ( FNR==2 ), se as condições forem atendidas, imprimir o nome do arquivo é um formato adequado para xargs (a entrada xargs é tratada como uma lista de palavras separadas por espaços em branco ou novas linhas e onde aspas simples e duplas e barras invertidas podem ser usadas para escapar dos separadores ou uns dos outros). Por exemplo, um arquivo chamado ./That's tough.log seria exibido como './That'\''s tough.log' .

xargs usa essa entrada para passar o maior número de argumentos possível para sh . Precisamos do wrapper sh porque o diretório de destino deve ser o último argumento. Nós queremos o -i porque desde que os arquivos acabam no mesmo diretório, há espaço para os dados serem perdidos se dois arquivos com o mesmo nome em diretórios diferentes estiverem sendo movidos. Precisamos que o stdin de mv (para o prompt -i ) seja não o pipe de find , daí o uso de um fd temporário 3 para encaminhar o stdin externo para sh de sh para definir o valor de mv nessa.

    
por 08.08.2017 / 12:53