linux - renombrar - ¿Cómo unir varias líneas de nombres de archivos en uno con un delimitador personalizado?
renombrar directorio linux (19)
EDIT : Simplemente " ls -m " si desea que su delimitador sea una coma
¡Ah, el poder y la sencillez!
ls -1 | tr ''/n'' '',''
Cambia la coma " , " a lo que quieras. Tenga en cuenta que esto incluye una "coma final"
Me gustaría unir el resultado de ls -1
en una línea y delimitarlo con lo que quiera.
¿Hay algún comando estándar de Linux que pueda usar para lograr esto?
Agregando a la respuesta de majkinetor, aquí está la manera de eliminar el delimitador de cola (ya que no puedo comentar bajo su respuesta todavía):
ls -1 | awk ''ORS=","'' | head -c -1
Simplemente elimine tantos bytes finales como cuente su delimitador.
Me gusta este enfoque porque puedo usar delimitadores de múltiples caracteres + otros beneficios de awk
:
ls -1 | awk ''ORS=", "'' | head -c -2
Creo que este es impresionante
ls -1 | awk ''ORS=","''
ORS es el "separador de registro de salida", por lo que ahora sus líneas se unirán con una coma.
Este comando es para los fans de PERL:
ls -1 | perl -l40pe0
Aquí 40 es el código octal de ascii para el espacio.
-p procesará línea por línea e imprimirá
-Me encargaré de reemplazar el / n con el carácter ascii que proporcionamos.
-e es informar a PERL que estamos realizando la ejecución de la línea de comandos.
0 significa que en realidad no hay comando para ejecutar.
perl -e0 es igual que perl -e ''''
Esto reemplaza la última coma con una nueva línea:
ls -1 | tr ''/n'' '','' | sed ''s/,$//n/''
ls -m
incluye nuevas líneas en el carácter de ancho de pantalla (80º por ejemplo).
Mayormente Bash (solo ls
es externo):
saveIFS=$IFS; IFS=$''/n''
files=($(ls -1))
IFS=,
list=${files[*]}
IFS=$saveIFS
Usando readarray
(también mapfile
como mapfile
) en Bash 4:
readarray -t files < <(ls -1)
saveIFS=$IFS
IFS=,
list=${files[*]}
IFS=$saveIFS
Gracias a gniourf_gniourf por las sugerencias.
La combinación de la configuración de IFS
y el uso de "$*"
puede hacer lo que desee. Estoy usando un subshell para no interferir con los $ IFS de este shell.
(set -- *; IFS=,; echo "$*")
Para capturar la salida,
output=$(set -- *; IFS=,; echo "$*")
La forma sed,
sed -e '':a; N; $!ba; s//n/,/g''
# :a # label called ''a''
# N # append next line into Pattern Space (see info sed)
# $!ba # if it''s the last line ($) do not (!) jump to (b) label :a (a) - break loop
# s//n/,/g # any substitution you want
Nota :
Esto es lineal en complejidad, sustituyendo solo una vez después de que todas las líneas se agreguen en el Espacio de Patrones de sed.
La answer @ AnandRajaseka, y algunas otras respuestas similares, como here , son O (n²), porque sed tiene que hacer un sustituto cada vez que se agrega una nueva línea en el Espacio de Patrones.
Comparar,
seq 1 100000 | sed '':a; N; $!ba; s//n/,/g'' | head -c 80
# linear, in less than 0.1s
seq 1 100000 | sed '':a; /$/N; s//n/,/; ta'' | head -c 80
# quadratic, hung
No reinventes la rueda.
ls -m
Hace exactamente eso.
Para evitar una posible confusión de nueva línea para tr podríamos agregar la marca -b a ls:
ls -1b | tr ''/n'' '';''
Parece que las respuestas ya existen.
Si quieres el formato a a, b, c
, usa ls -m
( respuesta de Tulains Córdova )
O si quieres formato abc
, usa ls | xargs
xargs (versión simplificada de la respuesta de Chris J )
O si quieres cualquier otro delimitador como |
, usa ls | paste -sd''|''
ls | paste -sd''|''
(aplicación de la respuesta de Artem )
Parsing ls
en general no se recomienda , por lo que una mejor alternativa es utilizar find
, por ejemplo:
find . -type f -print0 | tr ''/0'' '',''
O usando find
y paste
:
find . -type f | paste -d, -s
Para unir líneas múltiples en general (no relacionadas con el sistema de archivos), marque: Concisión y "unión" portátil en la línea de comandos de Unix .
Puede usar chomp para fusionar varias líneas en una sola línea:
perl -e ''while (<>) {if (/ / $ /) {chomp; } print;} ''bad0> prueba
ponga la condición de salto de línea en la instrucción if. Puede ser un carácter especial o cualquier delimitador.
Puedes usar:
ls -1 | perl -pe ''s//n$/some_delimiter/''
Si la versión de xargs admite la marca -d, esto debería funcionar
ls | xargs -d, -L 1 echo
-d es la bandera delimitadora
Si no tiene -d, puede probar lo siguiente
ls | xargs -I {} echo {}, | xargs echo
El primer xargs le permite especificar su delimitador, que es una coma en este ejemplo.
Similar a la primera opción pero omite el delimitador final
ls -1 | paste -sd "," -
solo bash
mystring=$(printf "%s|" *)
echo ${mystring%|}
ls
produce una salida de columna cuando se conecta a una tubería, por lo que el -1
es redundante.
Aquí hay otra respuesta de Perl usando la función incorporada de join
que no deja un delimitador final:
ls | perl -F''/n'' -0777 -anE ''say join ",", @F''
El oscuro -0777
hace que Perl lea toda la entrada antes de ejecutar el programa.
Alternativa sed que no deja un delimitador al final.
ls | sed ''$!s/$/,/'' | tr -d ''/n''
ls
tiene la opción -m
para delimitar la salida con ", "
una coma y un espacio.
ls -m | tr -d '' '' | tr '','' '';''
canalizar este resultado a tr
para eliminar el espacio o la coma le permitirá canalizar el resultado nuevamente a tr
para reemplazar el delimitador.
en mi ejemplo sustituyo el delimitador con el delimitador ;
reemplazar con el delimitador de un carácter que prefiera, ya que solo representa el primer carácter de las cadenas que pasa como argumentos.
sed -e :a -e ''/$/N; s//n///n/; ta'' [filename]
Explicación:
-e
- denota un comando para ser ejecutado
:a
- es una etiqueta
/$/N
: define el alcance de la coincidencia para la línea actual y (N) ext.
s//n///n/;
- reemplaza todo EOL con /n
ta;
- Ir a etiquetar a si el partido es exitoso
Tomado de mi blog .