Unix: как заархивировать только N первых файлов в каждой папке?

Мой продуманный ответ: пойдите для mu4e и offlineimap вместо этого.

Я отказался от когда-либо попытки получить способ Rmail-Mailmove интегрировать электронную почту в emacs. Используя Rmail для задач системного администратора на источнике местной почты, я был рад попытаться расширить его до использования удаленного почтового источника IMAP. Однако разбив мою голову о трудности я встретился с Rmail и Movemail и затем Охотой к перемене мест с emacs, я понял, что тратил впустую свое время. Идея состояла в том, чтобы дополнить мой набор хитрых приемов org-режима путем добавления ссылок от документов org-режима до электронных писем.

Я столкнулся - и в конечном счете обосновался на - mu4e, который настолько легче установить и настроить; имеет хорошую документацию; интегрируется с org-режимом; и (одновременно с этой регистрацией в марте 2013) быть активно сохраняемым; и до сих пор работал очень выразительно.

7
17.08.2015, 20:17
7 ответов
for d in ./*/
do
    cd "$d"
    tar -rvf ../backup.tar $(ls | tail -10)
    cd ..
done
gzip backup.tar

другой вариант

find * -prune -type d -exec bash -c 'printf "%s\n" $0/* | tail -10' {} \; |
tar czvf backup.tar.gz -T -
1
27.01.2020, 20:17

Поскольку вывод find плоский, вы не знаете, какие файлы принадлежат тем же каталогам, не глядя на пути. Альтернативой является использование нескольких find (по одному на папку) без необходимости смотреть на пути. Вот что я сделал. Чтобы сохранить до 10 файлов в каждой подпапке, используйте что-то вроде этого:

for dir in $(find . -type d); do
  find "$dir" -maxdepth 1 -type f -printf "\"%p\"\n" | tail -10
done | xargs tar cvfz backup.tar.gz

Это рекурсивно находит все каталоги в текущей папке. Для каждого каталога он находит до 10 файлов в точно этой папке ( -maxdepth 1 ). После завершения всего цикла команда tar выполняется для всех файлов, которые были выведены циклом. Я также учел имена каталогов и папок с пробелами, заключив в кавычки $ dir и заставив find печатать каждое имя файла в кавычках с помощью параметра -printf .

2
27.01.2020, 20:17

Предположим, что ваш главный каталог - / tmp / dir , из которого вы хотите заархивировать только N (например, N = 10) файлов каждой (под) папки в backup.tar. gz файл.

Пример дерева для / tmp / dir :

dir/                                                                                                                                                                                                           
├── one
│   ├── one10.txt
│   ├── one11.txt
│   ├── one1.txt
│   ├── one2.txt
│   ├── one3.txt
│   ├── one4.txt
│   ├── one5.txt
│   ├── one6.txt
│   ├── one7.txt
│   ├── one8.txt
│   ├── one9.txt
│   └── one_deep
│       ├── one_deep1
│       ├── one_deep10
│       ├── one_deep11
│       ├── one_deep2
│       ├── one_deep3
│       ├── one_deep4
│       ├── one_deep5
│       ├── one_deep6
│       ├── one_deep7
│       ├── one_deep8
│       └── one_deep9
├── three
│   ├── three10.txt
│   ├── three11.txt
│   ├── three1.txt
│   ├── three2.txt
│   ├── three3.txt
│   ├── three4.txt
│   ├── three5.txt
│   ├── three6.txt
│   ├── three7.txt
│   ├── three8.txt
│   ├── three9.txt
│   └── three_deep
│       ├── three_deep1
│       ├── three_deep10
│       ├── three_deep11
│       ├── three_deep2
│       ├── three_deep3
│       ├── three_deep4
│       ├── three_deep5
│       ├── three_deep6
│       ├── three_deep7
│       ├── three_deep8
│       └── three_deep9

Код:

cd /tmp; for i in `find dir/* -type d`; do find $i -maxdepth 1 -type f | tail -n 10 | xargs -I file tar -rf backup.tar file; done; gzip backup.tar

Это создаст backup.tar.gz с 10 файлами каждая подпапка из-под / tmp / dir .

2
27.01.2020, 20:17

Используйте хэш в имени каталога и выдавайте имя файла только в том случае, если количество хеш-значений ниже порогового значения. Например.

find . -depth -type f \
| perl -MFile::Spec -nle '(undef,$d,$f)=File::Spec->splitpath($_); print if $seen{$d}++ < 3' \
| tar ...
0
27.01.2020, 20:17

Самый простой (или самый простой для понимания) способ - использовать xargs с параметром -N max-args .

Имейте в виду, что ваш ввод всегда должен быть чем-то, что не требует командной строки, поэтому echo *. * будет работать как ввод, где ls *. * нет (слишком длинная командная строка ls)

find должно быть нормально, поскольку его аргументом является только путь, а не список файлов.

0
27.01.2020, 20:17

ОП также запросил это в Stackoverflow . Вот ответ, который я там предложил.

Выбор и порядок файлов в этом ответе определяется порядком из find , поэтому «первый» здесь не определен четко. Это также может зависеть от GNU Awk 4.1.0.

find . -type f |
awk -v N=10 -F / 'match($0, /.*\//, m) && a[m[0]]++ < N' |
xargs -r -d '\n' tar -rvf /tmp/backup.tar

gzip /tmp/backup.tar

Комментарии:

  1. используйте find.-type f , чтобы гарантировать, что файлы имеют начальный префикс имени каталога, поэтому следующий шаг может работать
  2. - команда awk отслеживает такие ведущие имена каталогов и выдает полные имена пути до N ( 10, здесь) были созданы файлы с тем же начальным каталогом (возможно, более простое использование awk - разделение шаблона информации и программы - может быть более переносимым)
  3. используйте xargs для вызова tar - мы собираем обычные имена файлов, и они должны быть аргументами для этой команды архивирования
  4. xargs может вызывать tar более одного раза, поэтому мы добавим (опция -r) в простой архив, а затем сжать его после того, как все будет написано

Кроме того, вы можете не захотеть записывать файл резервной копии в текущий каталог, так как вы его сканируете - вот почему это предложение записывается в / tmp.

0
27.01.2020, 20:17

Если ваш pax поддерживает параметр -0 , с zsh :

print -rN dir/**/*(D/e:'reply=($REPLY/*(ND^/[1,10]))':) |
  pax -w0 | xz > file.tar.xz

Он включает первые 10 файлов, не относящихся к каталогам, каждого каталога в список отсортирован по имени файла. Вы можете выбрать другой порядок сортировки, добавив квалификатор glob om (упорядочить по времени изменения, Om , чтобы отменить порядок), oL (упорядочить по длине) , non (сортировать по имени, но численно) ...

Если у вас нет стандартной команды pax или она не поддерживает -0 , но у вас есть команда GNU tar , вы можете:

print -rN -- dir/**/*(D/e:'reply=($REPLY/*(ND^/[1,10]))':) |
  tar --null -T - -cjf file.tar.xz

Если вы не можете использовать zsh , но имеете доступ к bash ( оболочки проекта GNU), вы могли бы сделать:

find dir -type d -exec bash -O nullglob -O dotglob -c '
  for dir do
    set -- "$dir/*"; n=0
    for file do
      if [ ! -d "$file" ] || [ -L "$file" ]; then
        printf "%s\0" "$file"
        (( n++ < 10 )) || break
      fi
    done
  done' bash {} + | pax -0w | xz > file.tar.xz

Это было бы значительно менее эффективно.

4
27.01.2020, 20:17

Теги

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