Escapar correctamente barra diagonal en script bash para usar con sed


14

Estoy tratando de determinar el tamaño de los archivos que se copiarían nuevamente al sincronizar dos carpetas ejecutando rsync en modo seco y luego resumiendo los tamaños de los archivos enumerados en la salida de rsync.

Actualmente estoy atascado en el prefijo de los archivos por su carpeta principal. Descubrí cómo prefijar líneas usando sed y cómo escapar usando sed, pero tengo problemas para combinar esos dos.

Así de lejos llegué:

source="/my/source/folder/"
target="/my/target/folder/"
escaped=`echo "$source" | sed -e 's/[\/&]/\\//g'`
du `rsync -ahnv $source $target | tail -n +2 | head -n -3 | sed "s/^/$escaped/"` | awk '{i+=$1} END {print i}'

Este es el resultado que obtengo de bash -x myscript.sh

+ source=/my/source/folder/
+ target=/my/target/folder
++ echo /my/source/folder/
++ sed -e 's/[\/&]/\//g'
+ escaped=/my/source/folder/
+ awk '{i+=$1} END {print i}'
++ rsync -ahnv /my/source/folder/ /my/target/folder/
++ sed 's/^//my/source/folder//'
++ head -n -3
++ tail -n +2
sed: -e expression #1, char 8: unknown option to `s'
+ du
80268

Cualquier idea sobre cómo escapar adecuadamente sería muy apreciada.

Respuestas:


28

En realidad, no necesita molestarse en escapar del /. Del manual de GNUsed :

Los /caracteres pueden ser reemplazados uniformemente por cualquier otro carácter individual dentro de cualquier scomando dado .

Por ejemplo:

echo 'foobar' | sed -e 's#foo#bar#'

da la salida

barbar

44
Esto debería ser lo primero en la página de manual de sed
Más claro

¿Alguna como en 'any' *?
Ujjwal Singh

0

Si está intentando contar los datos, es probable que desee omitir cualquier subdirectorio posible. Esto puede no ser aplicable, pero siempre es mejor evitar cualquier rareza. Aquí está mi directorio fuente. Todos estos archivos se crearon con tacto, por lo que ocupan 0 espacios.

$ find source
source
source/5832
source/5832/5832_1.png
source/5832/5832_2.png
source/5831
source/5831/5831_1.png
source/5830
source/5830/5830_3.png
source/5830/5830_1.png
source/5830/5830_2.png

No debería necesitar escapar en ningún lugar tan cerca como lo está haciendo. El bloque sed aquí hará lo siguiente:
1d; elimine la primera línea de 'envío de la lista de archivos incrementales'
/ ^ $ /, $ d; elimine la línea en blanco que significa el final de la lista de archivos y todo lo que sigue.
// $ / d borra cualquier línea que termine en '/', que serían los directorios
Tenga en cuenta que puede escapar de las barras inclinadas diagonales (para responder la pregunta real).

$ du $(rsync -ahnv source target | sed '1d;/^$/,$d;/\/$/d')
0   source/5830/5830_1.png
0   source/5830/5830_2.png
0   source/5830/5830_3.png
0   source/5831/5831_1.png
0   source/5832/5832_1.png
0   source/5832/5832_2.png

Y para obtener puntos de bonificación adicionales, incluso puede sumar los resultados:

$ du -s $(rsync -ahnv source target | sed '1d;/^$/,$d;/\/$/d') | awk '{x+=$1;print $0} END {print "sum: "x}'
0   source/5830/5830_1.png
0   source/5830/5830_2.png
0   source/5830/5830_3.png
0   source/5831/5831_1.png
0   source/5832/5832_1.png
0   source/5832/5832_2.png
sum: 0

Sin embargo, si está haciendo esto con el directorio ya totalmente sincronizado, obtendrá resultados divertidos:

76  .
sum: 76
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.