Como colocar todas as linhas juntas no arquivo / para todos os arquivos em um diretório

0

Eu tenho centenas de arquivos em um diretório que contém linhas de texto. Eu quero concatenar todas as linhas em um arquivo em uma única linha. Eu gostaria de fazer isso para todos os arquivos em uma única passagem. cat parece não funcionar aqui

Exemplo

File_1

atagacat
agataga
ctcatctat
tagcatag

File_1_cat

atagacatagatagactcatctattagcatag

Arquivo_2

atagacat
agataga
ctcatctat
tagcatag

Arquivo_2_cat

atagacatagatagactcatctattagcatag
    
por Josh 02.03.2017 / 07:58

8 respostas

4

Simples cat + tr deve ser suficiente. Se não, talvez algo esteja errado com o seu sistema:

sh-4.2$ cat file1 file2 
atagacat 
agataga 
ctcatctat 
tagcatag 
atagacat 
agataga 
ctcatctat 
tagcatag
sh-4.2$ cat file1 file2 |tr -d '\n'
atagacatagatagactcatctattagcatagatagacatagatagactcatctattagcatag

Teste on-line aqui: link

Atualizar

Após seu esclarecimento nos comentários, você precisa remover novas linhas de cada arquivo separadamente e não juntar todos os arquivos juntos (ps: não coloque clarificações úteis nos comentários - edite sua pergunta principal), você pode usar algo como:

perl -pe 's/\n//g' file >file_cat #perl -pe is directly equivalent to 'sed'.  

Você também pode usar o perl -pe para fazer substituições de lote em mais arquivos de uma só vez:

perl -pe 's/\n//g' -i file{1..100) #-i : in-place replacements in each file
OR
perl -pe 's/\n//g' -i.bak file{1..100) #in-place replacement keeping also a backup of original file

ALSO this works for all txt files in a directory
perl -pe 's/\n//g' -i.bak *.txt #in line replacement of all txt files in current directory keeping also a back up file

Você pode usar um loop como mencionado em outras respostas ou assim:

while IFS= -r -d '' fname;do 
  perl -pe 's/\n//g' "$fname" >"${fname}_cat"
  #any other command you might need like echo,cat,whatever
done < <(find . -maxdepth 1 -type f -name 'file*' -print0)
    
por 02.03.2017 / 08:50
2
for name in ./*; do
  test -f "$name" && (tr -d '\n'; echo) <"$name" >"${name}_cat"
done

Isso removerá todas as novas linhas em todos os arquivos regulares (separadamente) no diretório atual (isso é o que o tr -d '\n' faz). O echo irá certificar-se de que há uma nova linha no final da linha em cada arquivo gerado.

    
por 02.03.2017 / 10:51
1

Não use tr para isso. tr -d '\n' remove todos os caracteres de nova linha. Um arquivo não vazio que não possui caractere de nova linha não é um arquivo de texto. Você precisa de um caractere de nova linha no final para que uma sequência de caracteres seja considerada como uma linha de texto adequada.

O comando canônico para unir todas as linhas em uma única é o comando paste:

 for file in ./*; do paste -sd '
for file in ./*; do
  [ ! -f "$file" ] || paste -sd '
file (./*(N-.)) do paste -sd '
 for file in ./*; do paste -sd '
for file in ./*; do
  [ ! -f "$file" ] || paste -sd '
file (./*(N-.)) do paste -sd '%pre%' - < $file > ${file}_cat
' - < "$file" > "${file}_cat" done
' "$file" > "${file}_cat"; done
' - < $file > ${file}_cat
' - < "$file" > "${file}_cat" done
' "$file" > "${file}_cat"; done

Isso faria isso para todos os arquivos não ocultos (independentemente do seu tipo - regular, symlink, diretório ...) no diretório atual. Se não houver nenhum arquivo não oculto, em shells diferentes de zsh , isso causaria um erro% depaste e criaria um arquivo *_cat vazio.

Também criaria arquivos file_cat vazios para arquivos que não podem ser abertos. Para evitar alguns desses problemas, você pode preferir:

%pre%

em vez disso ( -f é considerar apenas arquivos regulares ou links simbólicos para arquivos regulares), ou melhor e menor com zsh :

%pre%

(adicione o qualificador D glob para incluir arquivos ocultos).

-d 'paste' é a maneira padrão de especificar um separador vazio (não não significa um separador de caracteres NUL). Algumas -d '' implementações suportam paste para isso também, embora isso não seja portável (outras %code% implementações se queixariam do delimitador que faltava).

    
por 02.03.2017 / 14:22
0

Você pode usar tr em um loop dessa maneira:

for file in *; do
  [[ -f "$file" ]] || continue  # skip if not a regular file
  printf "%s\n" $(tr -d '\n' < "$file") > "$file"_cat
done

O \n em printf garante que adicionamos uma nova linha no final da linha concatenada.

    
por 02.03.2017 / 08:04
0

com awk :

awk '{printf $0> (FILENAME"_cat")}' *

Se você precisar de uma nova linha no final do novo arquivo:

awk '{printf $0> (FILENAME"_cat")}' *; sed -i -e '$a\' *_cat
    
por 02.03.2017 / 08:45
0

Usando o Vim:

vim -Nesc 'bufdo! %j! | w %_cat' -c 'qa!' *
  • -Nesc <command> é usado para executar <command> em ex-modo silencioso não compatível, o que é útil para o script do Vim.
  • bufdo! <command> executa o comando em cada buffer, não parando por arquivos alterados
  • %j! une todas as linhas sem inserir espaços (apenas j adiciona espaços), % sendo todas as linhas em um contexto de intervalo
  • w %_cat salva o arquivo atual em <filename>_cat , % sendo o nome do arquivo atual em um contexto de nome de arquivo
  • -c 'qa!' finalmente, feche sem salvar todos os arquivos.
por 02.03.2017 / 08:45
0

Você pode usar awk para isso:

for i in file*; do
    awk '{gsub(/[[:space:]]*/, "");printf $0}' $i > ${i}_cat
done

em que gsub faz o seguinte (citado no manual ) :

gsub(regexp, replacement [, target])

Search target for all of the longest, leftmost, nonoverlapping matching substrings it can find and replace them with replacement. The ‘g’ in gsub() stands for “global,” which means replace everywhere. For example:

{ gsub(/Britain/, "United Kingdom"); print }

replaces all occurrences of the string ‘Britain’ with ‘United Kingdom’ for all input records.

The gsub() function returns the number of substitutions made. If the variable to search and alter (target) is omitted, then the entire input record ($0) is used. As in sub(), the characters ‘&’ and ‘\’ are special, and the third argument must be assignable.

    
por 02.03.2017 / 08:09
0
find . -maxdepth 1 -type f -exec perl -i -l -0777pe 'y/\n//d' {} +

find pega arquivos do diretório atual sem fazer recursão e os entrega para Perl em um grupo, que então vai em frente e os retira de novas linhas e armazena as mudanças dentro de cada arquivo.

find . -maxdepth 1 -type f -exec sed -i -e '$!{N;s/^/\n/;D;};s/\n//g' {} +

No entanto, outros métodos para uma linha de um arquivo são:

perl -i -lpe '$\ = eof ? "\n" : ""' yourfile
sed  -i -e   'H;$!d;g;s/\n//g'      yourfile

< yourfile sed 's/.*/[&]/' | dc -e '[[]pq]sq [?z0=q n z0=?]s? l?x'
    
por 02.03.2017 / 08:37