No se puede cantar una cadena de un file debajo de una cadena de otro file

He encontrado un problema extraño al concatenar los files usando el command cat . Tengo dos files con una cadena en cada uno de ellos:

file1:

 ABC 

file2:

 DEF 

O bien hago cat file1 file2 o hago cat file1 >> file2 . Espero una salida como se muestra a continuación:

 ABC DEF 

Sin embargo, tengo un resultado divertido como este:

 ABCDEF 

Revisé los files y no hay espacio ni caracteres adicionales. Sin embargo, cuando borro manualmente de la parte posterior de la cadena, ni siquiera veo un solo caracter. Funciona bien. Supongo que debe haber algún tipo de carácter o línea "oculta" que no puedo ver.

Me ha estado molestando mucho porque tengo toneladas de files para concatenar. No puedo hacer lo mismo manualmente.

Cualquier ayuda es apreciada.

paste es probablemente el medio más fácil (por no decir extremadamente eficiente) a su disposition para manejar este problema.

 printf abc >file1 printf def >file2 paste -sd\\n file[12] 

 abc def 

Cuando se invoca paste -por lo general, leerá cada uno de sus files de input nombrados a su vez y paste el resultado de cada línea dentro de cada file en una <tab> o en una cadena de eliminador -d especificada. Mientras que paste siempre terminará su salida de cada file con una línea \n ewline, aquí el -d elimitador también se especifica como \n ewline, por lo que simplemente introducirá su input en el resultado con la exception de que cada file siempre termina en una \n ewline.


Como señala Peter a continuación, un file vacío puede causar que paste emita una línea \n adicional. Si esto es un problema, prácticamente se puede aplicar el mismo método con sed que no lo hará:

 : > file0 sed '' file[012] 

 abc def 

Ahora bien, con este método, (con GNU sed al less) puede haber un problema diferente. Cualquier sed siempre escribirá una \n ewline antes de tirar en otra línea, pero si es la última línea de toda la serie concatenada de files de input, entonces algunos sed s (como GNU) pueden no anexar una nueva línea al final . Por ejemplo, con mis files de input, la def no es seguida por una nueva línea.

Y si eso es un problema, bueno …

 sed '' file[012] | paste -sd\\n 

… la tubería anterior probablemente debería cubrir todas sus bases.

Como dice Peter, tu primer file no tiene un carácter de final de línea. Probablemente puedas verificarlo con ls -l — si son exactamente tres caracteres, esto es todo.

Si desea "cat" los files agregando una nueva línea solo si la nueva línea no estaba allí, puede usar el truco que aquí se explica.

Si tienes estos tres files:

 [romano:~/tmp] % ls -l f1 f2 f3 -rw-rw-r-- 1 romano romano 3 Jul 12 14:58 f1 -rw-rw-r-- 1 romano romano 4 Jul 12 15:03 f2 -rw-rw-r-- 1 romano romano 4 Jul 12 15:03 f3 [romano:~/tmp] % cat f1 f2 f3 ABCDEF GHI 

donde f1 no tiene final de línea en la última línea, mientras que los otros lo hacen, puedes hacer lo siguiente:

 [romano:~/tmp] % sed -e '$a\' f1 f2 f3 ABC DEF GHI 

sed es un EDITOR Stream, y le está orderando que imprima todo sin cambios y la última línea no agregue nada — pero agregó implícitamente una nueva línea cuando opera, por lo que resuelve el problema.

Tenga en count que solo con el uso del elemento cat + echo agregará una línea nueva siempre . entonces tendrías dos donde tuviste uno:

 [romano:~/tmp] % for i in f?; do cat $i; echo; done; ABC DEF GHI [romano:~/tmp] % 

Parece que su file1 no tiene nueva línea final. Si desea concatenar una list de files. Primero puede verificar cada uno y cat una nueva línea donde sea necesario, de la siguiente manera:

 # make some sample files printf "%s\n" abc > file1 printf "%s" def > file2 # no trailing newline printf "%s\n" ghi > file3 printf "%s" jkl > file4 # no trailing newline 

 # find files to concatenate and build a sorted array `f[]` unset fi; while IFS= read -r -d $'\0' path; do f[i++]="$path" done < <(find . -type f -name 'file[0-9]' -print0 | sort -z) # build the `cat` command cmd=cat tmp="$(mktemp)"; echo >$tmp # a file which contains only `\n` for file in "${f[@]}"; do lasthex=$(tail -c1 $file | hexdump -ve '1/1 "%02x"') [[ -z $lasthex ]] && continue # skip enpty files [[ $lasthex == 0a ]] && nl= || nl=" $tmp" cmd="$cmd \"$file\"$nl" done # execute the `cat` command eval "$cmd" 

El resultado concatenado es:

 abc def ghi jkl 

El command generado es:

 cat "./file1" "./file2" /tmp/tmp.z7iKccY0T9 "./file3" "./file4" /tmp/tmp.z7iKccY0T9 

Te faltan nuevas líneas. Podrías hacerlo

 cat file1; echo; cat file2; 

o crea un file que tiene solo un freno de línea y lo hace

 cat file1 NEWLINEFILE file2 

o haz esto con un ciclo como este

 for i in find[1-2]; do cat $i; echo; done; 

para ejecutar *, cat cada file y agregar una nueva línea después.

Con $(find OPTIONS) lugar de find[1-2] , puede refinar su selección.