Copie a primeira linha de um arquivo para outros arquivos usando xargs e sed

0

Eu tenho uma lista de arquivos CSV divididos. Como posso copiar o primeiro cabeçalho CSV para o restante dos arquivos CSV?

profiles00.csv profiles01.csv profiles02.csv profiles03.csv ...

Isto é o que tenho agora, mas como envio a saída para novos arquivos ou substituo os arquivos existentes?

find . -name \*.csv -print0 | xargs -0 -I {} -P 100 sed -e '1r {}' -e 'q' profiles00.csv

    
por angelokh 17.05.2018 / 03:55

3 respostas

2

Aqui está uma maneira de lidar com seu problema específico:

find . -maxdepth 1 -type f -name "profiles*.csv" ! -name "profiles00.csv" -exec sed -i -e '1!b' -e 'R profiles00.csv' -e 'N' {} +

Escrito de maneira multilinha como:

find . -maxdepth 1 \
    -type f \
    -name "profiles*.csv" ! -name "profiles00.csv" \
    -exec sed -i -e '1!b' \
                 -e 'R profiles00.csv' \
                 -e 'N' \
     {} +

deve ser lido como: encontrar utilitário

  • -maxdepth 1 = > ande apenas no diretório atual, normalmente ele recorre até a hierarquia mais baixa.

  • -type f = > durante a caminhada, selecione apenas os arquivos regulares.

  • -name "profiles*.csv" ! -name "profiles00.csv" = > De todos os arquivos regulares, selecione somente aqueles que têm perfis * .csv como seus nomes de base e filtram o arquivo "profiles00.csv", já que este é o arquivo de cabeçalho.

  • -exec sed -i -e '1!b' -e 'R profiles00.csv' -e 'N' {} +

  • -i option = > editar arquivos no lugar do GNU sed assumido

  • -e option = > o código sed segue

    • 1!b = > não toque nas linhas que não são as primeiras.

    • R profiles00.csv = > leia uma linha (já que é a primeira vez, será a primeira linha) do arquivo profiles00.csv. Então, essencialmente, o cabeçalho é retirado do arquivo profiles00.csv. Mas ainda não foi impresso.

    • N = > Leia na próxima linha o espaço do padrão. isso libera o buffer de leitura e depois disso o espaço de padrão real é liberado (linhas 1,2) do arquivo atual sendo operado pelo sed.

  • {} + fará com que encontre forneça os vários arquivos selecionados de uma só vez ao utilitário sed e o GNU sed é capaz de manipular vários arquivos com a opção -i . Especificamente, os números de linha são redefinidos para um novo arquivo lido.

≠ ================ Posix maneira ======

 LC_ALL=C  \
 find . ! -name . -prune -type f  \
     -name 'profiles??*.csv'      \
   ! -name 'profiles*[!0-9]*.csv' \
   ! -name 'profiles00.csv'       \
     -exec sh -c '
              shift "$1"
              head -n 1 < profiles00.csv > header
              for arg do
                 printf "0r header\nw\nq\n" | ed -s "$arg"
              done
          ' 2 1 {} +

Aqui dispensamos sed e recorremos ao ed.

  • 0r = > irá inserir o conteúdo do arquivo mencionado, no início do arquivo sendo editado por ed.
  • w = > irá gravar no arquivo, congelando assim todas as alterações feitas.
  • q = > vai sair do editor ed.
por 17.05.2018 / 13:46
1

Você não precisa de xargs

Comando:

find . -maxdepth 1 ! -name "profiles00.csv" -a -name "*csv" -exec sed -i "1s/^/$(head -1 profiles00.csv)\n/" {} \;

Aqui estou usando find para selecionar arquivos e sed para edição em vigor

Explicação

find

  • maxdepth 1 - para selecionar apenas arquivos no diretório imediato e não no subdiretório, se você quiser editar arquivos no subdiretório também, pode remover essa opção
  • ! -name "profiles00.csv" -a -name "*csv" - para selecionar todos os arquivos csv, mas não profiles00.csv, aqui -a means e e ! significa não

sed

  • -i - editar arquivos no lugar
  • 1 - endereço de linha
  • s/^/$(head -1 profiles00.csv)\n/ - para substituir o início do arquivo pelo texto especificado

head

  • -1 - para selecionar a primeira linha
por 17.05.2018 / 07:32
0

Este é um esboço de pseudocódigo não testado, portanto, pode não funcionar, mas eu faria algo como (primeiro faça backup dos arquivos para não sobrescrevê-los):

sed -i '1s/^/''head -n1 profiles00.csv''/' *.csv

explicado

Para mais informações sobre como inserir arquivos:

link

    
por 17.05.2018 / 05:11