Как определили другие, проблема с вашей командой заключается в том, что она включает каталоги, а tar архивирует их рекурсивно. Если каталог был недавно изменен, все файлы в нем и его подкаталогах будут включены, независимо от того, были они изменены или нет.
Если вы не хотите создавать резервные копии метаданных каталога, просто скажите find
не печатать имена каталогов. Недостаточно пропустить корень: то же самое может случиться и с подкаталогами.
find "$SOURCEDIR" -mtime -1 ! -type d -print | xargs -r tar -rcf "$ARCHIVE"
Использование xargs не работает с именами файлов, содержащими пробелы и некоторые другие специальные символы . Это легко исправить: используйте -exec
вместо xargs
.
find "$SOURCEDIR" -mtime -1 ! -type d -exec tar -rcf "$ARCHIVE" {} +
Если вы хотите создать резервную копию метаданных каталога, позвольте find
распечатать все и вместо этого указать tar
не рекурсивно переходить в подкаталоги. Поскольку find
выполняет рекурсию, tar
в этом не нуждается.
find "$SOURCEDIR" -mtime -1 -exec tar -rcf "$ARCHIVE" --no-recursion {} +
При таком подходе вы можете избежать использования tar -rc
и вместо этого решить проблему повторяющихся вызовов tar, сначала создавая архив только с корневым каталогом, а затем добавляя его в пакетах. (Почему корневой каталог? Потому что GNU tar боится создать пустой архив.)
tar -cf "$ARCHIVE" --no-recursion "$SOURCEDIR"
find "$SOURCEDIR" -mindepth 1 -mtime -1 -exec tar -rf "$ARCHIVE" --no-recursion {} +
Чистое bash решение
while IFS=\, read -r a b ; do echo "$a;$b" ; done <file.csv
Или просто для развлечения
paste -d\; <(cut -d, -f1 file.csv) <(cut -d, -f1 --complement file.csv)
g
в:
sed 's/,/;/g'
предназначен для глобально , то есть заменяет все вхождения ],
с ;
.
Если вы хотите делать только одну замену в строке, удалите g
:
sed 's/,/;/'
И для полноты:
Вы также можете указать, какое вхождение нужно заменить. Например, чтобы заменить только второе вхождение:
sed 's/,/;/2'
С помощью GNU sed
вы также можете заменить все вхождения, начиная со второго (фактически, все, кроме первого) на:
sed 's/,/;/2g'
To в этом случае выполните две замены:
sed 's/,/;/;s/,/;/'
Сложнее становится, когда шаблон может соответствовать замене (или ее частям), например, при замене ,
на <,>
. sed
не имеет встроенного механизма для решения этой проблемы. В этом случае вы можете использовать perl
вместо этого:
perl -pe '$i = 0; s/,/$i++ < 2 ? "<,>" : $&/ge'
perl -pe
- это perl
режим sed
(обратите внимание, что синтаксис регулярного выражения отличается). С флагом e
оператора s ///
замена рассматривается как код. Здесь мы заменяем ,
на <,>
только тогда, когда наш увеличиваемый счетчик <2.В противном случае мы заменяем ,
самим собой ( $ &
фактически ссылается на совпавшую строку, например &
в sed
s
команда).
Вы можете обобщить это для диапазона или набора замен. Как для 3 -го 5 -го и 7 -го до 9 -го :
perl -pe '$i = 0; s/,/$i++;
$i >=3 && $i <= 5 || $i >= 7 && $i <= 9 ? "<,>" : $&/ge'
Чтобы заменить только первое вхождение во всем вводе (в отличие от в каждой строке ):
sed -e 's/,/;/;t done' -e b -e :done -e 'n;b done'
То есть при первой успешной подстановке перейти в цикл, который просто печатает остальную часть ввода.
В GNU sed
вы можете использовать псевдоадрес 0 :
sed '0,/,/s//;/'
Я полагаю, что это опечатка, но команда
sed '/s/,/;/g'
, которую вы написали в своем вопрос совсем в другом.
Это делается:
sed '/start/,/end/g'
где start
- это s
, а end
- это ;
. То есть, применяя команду g
(замените пространство шаблонов содержимым удерживаемого пространства (здесь пусто, поскольку вы никогда ничего не удерживаете)) для разделов файла между разделами, содержащими s
и следующий, содержащий ;
.