Належне уникнення косої риски в баш-скрипті для використання з sed


14

Я намагаюся визначити розмір файлів, які були б знову скопійовані при синхронізації двох папок, запустивши rsync в сухому режимі, а потім підсумувати розміри файлів, перелічених у висновку rsync.

Наразі я застряг у префіксації файлів їх батьківською папкою. Я дізнався, як префікс рядків за допомогою sed і як уникнути використання sed, але у мене виникають проблеми при поєднанні цих двох.

Ось як далеко я дістався:

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

Це вихід, який я отримую з 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

Будь-які ідеї, як правильно втекти, були б дуже вдячні.

Відповіді:


28

Вам насправді не потрібно турбуватися про втечу /. З посібника GNUsed :

Ці /символи можуть бути рівномірно замінені будь-яким іншим символом в тому чи іншій sкоманді.

Наприклад:

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

дає вихід

barbar

4
Це має бути першим, що знаходиться на сторінці man для sed
Clearer

Як у "будь-якому" *?
Ujjwal Singh

0

Якщо ви намагаєтеся збільшити дані, ви, ймовірно, захочете пропустити будь-які можливі підкаталоги. Це може не застосовуватися, але завжди краще уникати будь-яких дивацтв. Ось мій вихідний каталог. Усі ці файли створені з дотиком, тому вони займають 0 місця.

$ 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

Вам не потрібно бігти ніде поблизу стільки, скільки ви робите. Блок sed тут буде робити наступне:
1d; видаліть перший рядок "надсилання додаткового списку файлів"
/ ^ $ /, $ d; видаліть порожній рядок, який означає кінець списку файлів і все після нього.
// $ / d видаліть будь-який рядок, що закінчується на '/', який би був каталогіми.
Зауважте, що ви можете уникнути косої риски за допомогою косої риски (щоб відповісти на фактичне запитання).

$ 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

А для додаткових бонусних балів ви навіть можете підрахувати результати:

$ 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

Якщо ви робите це з каталогом, який вже повністю синхронізований, він поверне смішні результати, хоча:

76  .
sum: 76
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.