Échapper correctement la barre oblique dans le script bash pour une utilisation avec sed

14

J'essaie de déterminer la taille des fichiers qui seraient nouvellement copiés lors de la synchronisation de deux dossiers en exécutant rsync en mode sec, puis en résumant les tailles des fichiers répertoriés dans la sortie de rsync.

Actuellement, je suis bloqué à préfixer les fichiers par leur dossier parent. J'ai découvert comment préfixer des lignes en utilisant sed et comment échapper en utilisant sed, mais j'ai du mal à combiner ces deux.

Voilà jusqu'où je suis arrivé:

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}'

Ceci est la sortie que j'obtiens 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

Toute idée sur la façon de s'échapper correctement serait très appréciée.

user331839
la source

Réponses:

28

Vous n'avez pas vraiment besoin de vous soucier de vous échapper /. Depuis le manuel GNUsed :

Les /caractères peuvent être uniformément remplacés par tout autre caractère unique dans une scommande donnée .

Par exemple:

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

donne la sortie

barbar
jjlin
la source
4
Cela devrait être la première chose dans la page de manuel de sed
Clearer
Tout comme dans 'tout' *?
Ujjwal Singh
0

Si vous essayez de compiler les données, vous souhaiterez probablement ignorer tous les sous-répertoires possibles. Cela peut ne pas être applicable, mais il est toujours préférable d'éviter toute bizarrerie. Voici mon répertoire source. Ces fichiers ont tous été créés avec le toucher, donc ils occupent 0 espace.

$ 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

Vous ne devriez pas avoir besoin de vous échapper autant que vous le faites. Le bloc sed ici fera ce qui suit:
1d; supprimez la première ligne de 'envoi d'une liste de fichiers incrémentielle'
/ ^ $ /, $ d; supprimez la ligne vierge qui signifie la fin de la liste des fichiers et tout ce qui se trouve après.
// $ / d supprime toute ligne se terminant par un '/', qui serait les répertoires.
Notez que vous pouvez échapper les barres obliques avec des barres obliques inverses (pour répondre à la question réelle).

$ 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

Et pour des points bonus supplémentaires, vous pouvez même cumuler les résultats:

$ 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

Si vous faites cela avec le répertoire déjà entièrement synchronisé, cela retournera des résultats amusants, cependant:

76  .
sum: 76
Falsenames
la source