AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 561600
Accepted
AGamePlayer
AGamePlayer
Asked: 2020-01-12 08:18:00 +0800 CST2020-01-12 08:18:00 +0800 CST 2020-01-12 08:18:00 +0800 CST

Como mantenho as primeiras 200 linhas de todos os arquivos csv em um diretório usando o bash?

  • 772

Eu tenho cerca de 50 arquivos csv muito grandes, eles têm milhares de linhas.

E eu só quero manter as primeiras 200 linhas para cada uma delas - tudo bem se os arquivos gerados substituirem os originais.

Qual comando devo usar para fazer isso?

bash files
  • 6 6 respostas
  • 5268 Views

6 respostas

  • Voted
  1. Best Answer
    Kusalananda
    2020-01-12T08:22:02+08:002020-01-12T08:22:02+08:00

    Supondo que o diretório atual contenha todos os arquivos CSV e que todos tenham um .csvsufixo de nome de arquivo:

    for file in ./*.csv; do
        head -n 200 "$file" >"$file.200"
    done
    

    Isso gera as primeiras 200 linhas de cada arquivo CSV para um novo arquivo usando heade um redirecionamento. O nome do novo arquivo é o mesmo do antigo, mas .200anexado ao final do nome. Não há verificação para ver se o novo nome de arquivo já existe ou não.

    Se pretender substituir os originais:

    for file in ./*.csv; do
        head -n 200 "$file" >"$file.200" &&
        mv "$file.200" "$file"
    done
    

    O &&no final do headcomando faz com que mvnão seja executado se houver algum problema com a execução do head.

    Se seus arquivos CSV estiverem espalhados em subdiretórios no diretório atual, use shopt -s globstare substitua o padrão ./*.csvno loop por ./**/*.csv. Isso localizará qualquer arquivo CSV dentro ou abaixo do diretório atual e executará a operação em cada um. O **padrão globbing corresponde "recursivamente" em subdiretórios, mas somente se a globstaropção shell estiver definida.


    Para arquivos CSV contendo dados com novas linhas incorporadas, o acima não funcionará corretamente, pois você pode truncar um registro. Em vez disso, você teria que usar alguma ferramenta compatível com CSV para fazer o trabalho para você.

    O seguinte usa CSVkit, um conjunto de ferramentas de linha de comando para análise e trabalho geral com arquivos CSV, juntamente com jq, uma ferramenta para trabalhar com arquivos JSON.

    Não há ferramenta no kit CSV que possa truncar um arquivo CSV em um ponto específico, mas podemos converter os arquivos CSV em JSON e usar jqpara gerar apenas os primeiros 200 registros:

    for file in ./*.csv; do
        csvjson -H "$file" | jq -r '.[:200][] | map(values) | @csv' >"$file.200" &&
        mv "$file.200" "$file"
    done
    

    Dado algum arquivo CSV como o exemplo abaixo,

    a,b,c
    1,2,3
    "hello, world",2 3,4
    "hello
    there","my good
    man",nice weather for ducks
    

    o csvjsoncomando produziria

    [
      {
        "a": "a",
        "b": "b",
        "c": "c"
      },
      {
        "a": "1",
        "b": "2",
        "c": "3"
      },
      {
        "a": "hello, world",
        "b": "2 3",
        "c": "4"
      },
      {
        "a": "hello\nthere",
        "b": "my good\nman",
        "c": "nice weather for ducks"
      }
    ]
    

    A jqferramenta então pegaria isso e, para cada objeto na matriz (restrito aos primeiros 200 objetos), extrairia os valores como uma matriz e formataria como CSV.

    Provavelmente é possível fazer essa transformação diretamente com csvpy, outra ferramenta no CSVkit, mas como minhas habilidades em Python são inexistentes, não tentarei encontrar uma solução que faça isso.

    • 43
  2. Paul_Pedant
    2020-01-12T10:11:28+08:002020-01-12T10:11:28+08:00

    As respostas anteriores copiam dados e substituem arquivos. Esta técnica deve manter os mesmos inodes, não copiar e rodar muito mais rápido. Para cada arquivo:

    (a) Encontre o comprimento de cada arquivo lendo as primeiras 200 linhas.

    (b) Trunque o arquivo para esse tamanho usando truncateGNU coreutils, ou com o truncateencontrado em alguns sistemas BSD:

    SZ="$( head -n 200 -- "${file}" | wc -c )"
    truncate -s "${SZ}" -- "${file}"
    
    • 25
  3. jesse_b
    2020-01-12T08:54:33+08:002020-01-12T08:54:33+08:00

    Usando sed com shell globbing:

    sed -ni '1,200p' *.csv
    

    Usando globbing/sed/paralelo:

    printf '%s\n' *.csv | parallel -- sed -ni '1,200p' {}
    

    Isso encontrará todos os .csvarquivos no diretório atual e os alimentará no GNU paralelo, que executará um comando sed neles para manter apenas as primeiras 200 linhas. Observe que isso substituirá os arquivos no local.

    Ou usando cabeça com paralelo:

    printf '%s\n' *.csv | parallel -- head -n 200 {} ">" {}.out
    

    Isso criará novos arquivos com o .outsufixo.

    • 15
  4. Stéphane Chazelas
    2020-01-13T23:59:22+08:002020-01-13T23:59:22+08:00

    Com ksh93 e uma implementação compatível com POSIX head(uma que deixa o cursor dentro de stdin logo após a última linha de saída), você pode fazer:

    for file in ~(N)./*; do
      [ -f "$file" ] || continue # skip non-regular files
      head -n 200 0<>; "$file" > /dev/null
    done
    

    O <>;operador de redirecionamento é uma variante do <>operador padrão que trunca o arquivo no local após o retorno do comando redirecionado, desde que o comando retorne com um status de saída bem-sucedido.

    Aqui, descartamos heada saída de , estamos interessados ​​apenas em sua capacidade de deixar o cursor logo após a 200ª linha.

    Infelizmente, o built-in do ksh93 head(que é ativado se você emitir builtin headou se /opt/ast/binestiver à frente de qualquer diretório com um headcomando nele $PATH) não se comporta POSIXly nesta instância. Ele lê a entrada em pedaços (como a maioria das outras headimplementações), mas não se preocupa em voltar ao final da 200ª linha quando invocado dessa maneira . Para forçá-lo a fazer essa busca de volta, precisamos executar um comando externo que anule o propósito de ter um built- headin em primeiro lugar:

    builtin head # enable ksh93's head builtin
    { head -n 200 && /bin/true; } 0<>; file > /dev/null
    

    Outra abordagem de trabalho que não envolve invocar um utilitário externo seria fazer uma busca explícita de deslocamento 0 após headretornos:

    builtin head # enable ksh93's head builtin
    for file in ~(N)./*; do
      [ -f "$file" ] || continue # skip non-regular files
      { head -n 200 && exec <#((CUR)); } 0<>; "$file" > /dev/null
    done
    

    Para entrada CSV especificamente e para reter os primeiros 200 registros CSV (em oposição às linhas, pois um registro CSV pode conter mais de uma linha (incorporada em "..."campos entre aspas), você pode usar ksh93's read -Sespecialmente projetados para ler CSVs em um loop:

    for file in ~(N)./*.csv; do
      [ -f "$file" ] || continue # skip non-regular files
      for ((i=0;i<200;i++)); do 
        IFS=, read -rSA discard
      done 0<>; "$file"
    done
    
    • 3
  5. Ryan
    2020-01-13T23:36:15+08:002020-01-13T23:36:15+08:00

    Eu sou relativamente novo, então, por favor, seja gentil. Gostaria de receber feedback construtivo se a solução que estou propondo não for a ideal.

    Eu criei 4 arquivos de amostra numerados de 1 a 4, por exemplo touch {1..4}, e cada arquivo contém 10 linhas de amostra, como no primeiro arquivo e linhas de 11 a 20 no próximo arquivo, assim por diante.

    Arquivo 1

    Line 1
    Line 2
    Line 3
    Line 4
    Line 5
    Line 6
    Line 7
    Line 8
    Line 9
    Line 10 
    

    Arquivo 2

    Line 11
    Line 12
    Line 13
    Line 14
    Line 15
    Line 16
    Line 17
    Line 18
    Line 19
    Line 20
    

    Para extrair as 2 primeiras linhas como exemplo (que podem ser extrapoladas para 200), o comando head -n 2 {1..4}retorna a saída;

    ==> 1 <==
    Line 1
    Line 2
    
    ==> 2 <==
    Line 11
    Line 12
    
    ==> 3 <==
    Line 21
    Line 22
    
    ==> 4 <==
    Line 31
    Line 32
    

    O comando pode redirecionar a saída para outro arquivo com o comandohead -n 2 {1..4} > ExtractedOutput

    • 1
  6. chepner
    2020-01-14T08:18:41+08:002020-01-14T08:18:41+08:00

    Use edpara truncar cada arquivo.

    for f in *.csv; do
      printf '201,$d\nwq\n' | ed "$f"
    done
    

    Se você quiser salvar um backup, pode ser mais fácil usá -lo ex. (Você também pode considerar exmais simples de usar, independentemente; basta soltar o w!%.bak|para pular a criação de um backup primeiro.)

    for f in *.csv; do
        ex -c 'w!%.bak|201,$d|wq' "$f"
    done
    
    • 1

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve