Слияние двух каталогов, не копируя файлы

С утилитами GNU, как найдено на Linux или Cygwin, можно сказать uniq разделить каждый блок файлов с тем же хешем. Вызов uniq с опцией --all-repeated удаляет уникальные файлы из списка в процессе.

sha1sum * |
sort | uniq -w 40 --all-repeated=prepend |
sed -e '/^$/ { N; d; }' -e 's/^[^ ]*  //' |
tr '\n' '\0' | xargs -0 rm --

Это не стоит усилия по этому простому, портативному awk сценарий: распечатайте каждую строку, если ее первое поле идентично первому полю предыдущей строки. Снова, это заботится об удалении уникальных файлов из списка.

sha1sum * |
sort |
awk '$1==h {print}  {h=$1}' |
tr '\n' '\0' | xargs -0 rm --

Вместо того, чтобы делать это вручную, Вы могли назвать fdupes.

fdupes -f

3
27.08.2017, 03:57
3 ответа

Ну, Вы могли иметь find должностное лицо mkdir.

cd /A/
find -type d -exec mkdir -p /C/{} \;

Или если структура является плоской как показано в Вашем примере, без find

cd /A/
for dir in */
do
    mkdir -p /C/"$dir"
done

и в обоих случаях то же снова для cd /B/.

7
27.01.2020, 21:10
  • 1
    я попробовал Ваше первое решение (структура не является плоской), но я боюсь, что не могу найти папку C. Где это, как предполагается, идет? –  fxm 05.09.2013, 11:50
  • 2
    @fxm: он просто сокращает Ваши имена папок. Где он говорит A, он имеет в виду то же самое, которое Вы назвали как Folder A. Так, C Folder C. Имена файлов с пробелами в них требуют внимательного отношения к заключению в кавычки, таким образом, более просто дать корректному примеру этот путь. –  Warren Young 05.09.2013, 12:12
  • 3
    Также обратите внимание, что этому нужны или полные пути или в пути относительно /A/ или /B/, например. ../C/ вместо C/. Я предположил, что B C был примером, и Вы знаете, как указать местоположение реальных каталогов. –  frostschutz 05.09.2013, 12:15
  • 4
    я понимаю это, но изменение /C/ ~/newFolder/ не делает, кажется, создает afroementionned папку в моем доме –  fxm 05.09.2013, 12:21
  • 5
    О, извините, мое плохое. Используйте \; вместо +. –  frostschutz 05.09.2013, 12:29

Если Вы просто хотите создать ту же структуру каталогов, можно звонить find пересекать каждое существующее дерево каталогов и вызов mkdir с правильным аргументом на каждом подкаталоге. Звонить mkdir -p тихо пропускать каталоги, которые уже существуют.

cd 'Folder A'
find . -type d -exec mkdir -p '/path/to/Folder C/{} '\;
cd 'Folder B'
find . -type d -exec mkdir -p '/path/to/Folder C/{} '\;

В zsh, предполагая это Folder A, Folder B и Folder C подкаталоги того же каталога:

mkdir -p Folder\ [AB]/**/*(/e\''REPLY=Folder\ C/${REPLY#*/}'\')

Если Вы хотите воспроизвести иерархию каталогов с полномочиями файла, можно назвать rsync и дать ему фильтр, который только включает каталоги а не регулярные файлы. Удостоверьтесь, что включали a / в конце исходных каталогов так, чтобы их содержание было скопировано непосредственно под /path/to/Folder C без создания /path/to/Folder C/path/to/Folder A и так далее.

rsync -a --include='*/' --exclude='*' '/path/to/Folder A/' '/path/to/Folder B/' '/path/to/Folder C'
2
27.01.2020, 21:10

Вот то, как я сделал бы это:

$ (find "Folder A"/* -type d ; find "Folder B"/* -type d) | \
           sed 's#[^/]\+/##' | xargs -I{} mkdir -p "Folder C"/{}

Подробнее

Это генерирует список подкаталогов под "Папкой" и Папкой B", тот список будет похож на это:

Folder A/A2
Folder A/C1
Folder B/B2
Folder B/B3
Folder B/C1

Передача по каналу того вывода через это sed команда удалит "Папку.." бит:

sed 's#[^/]\+/##'

Получающийся в этом:

A2
C1
B2
B3
C1

Примечание: Вышеупомянутое sed смотрит от левой стороны, находя все, что не является наклонной чертой до первой наклонной черты, этими символами затем не заменяют ни с чем, по существу удаляя их.

В этой точке Вы просто должны mkdir в соответствии с каталогом "Folder C", таким образом, мы будем использовать xargs сделать эту повторяющуюся задачу:

xargs -I{} mkdir -p "Folder C"/{}

Это говорит для принятия каждого аргумента как {} и замените им в следующую команду когда-либо, где существует соответствие {}.

Пример

Демонстрационные данные:

$ tree Folder\ {A,B,C}
Folder A
|-- A2
`-- C1
    `-- filea
Folder B
|-- B2
|   `-- fileb
|-- B3
`-- C1
Folder C

Примечание: См., что "Папка C" пуста для запуска.

Теперь мы выполняем нашу команду:

$ (find "Folder A"/* -type d ; find "Folder B"/* -type d) | \
           sed 's#[^/]\+/##' | xargs -I{} mkdir -p "Folder C"/{}

И нас оставляют со следующим:

$ tree Folder\ C
Folder C
|-- A2
|-- B2
|-- B3
`-- C1
0
27.01.2020, 21:10
  • 1
    Как насчет find A/ B/ -type d -print0 | sed -z ... | xargs -0 ...? –  frostschutz 05.09.2013, 20:52

Теги

Похожие вопросы