Сценарий Bash для цикла с находкой и многими каталогами

Я думаю, что очень трудно рекомендовать что-то здесь. Если Вы чувствуете себя прекрасно с Debian, остаются с ним. Для правильного решения для виртуализации я рекомендовал бы KVM, потому что это хорошо интегрируется в ядро, и это работает таким же образом многими другими инструментами Linux. Я понятия не имею, насколько хороший это когда дело доходит до связанных с GPU задач. Я просто испытал бы его.

Также знайте, что устойчивость ОС во многом зависит от аппаратных средств и драйверов для их.

BTW я использую KVM на openSUSE 11.4 без любых проблем.

1
05.10.2012, 03:43
4 ответа

Не анализируйте находят вывод и просто используют оболочку globbing - это более безопасно и встроено в оболочку. Shell, созданный-ins как for не подвергаются тому же пределу длины списка аргументов как внешние процессы, так как никакие вызовы не делают exec* сделаны.

for dir in ./*/; do
    # ...
done
6
27.01.2020, 23:11
  • 1
    я на самом деле опустил это, потому что я не думал, что он имел значение, но я должен найти только каталоги измененными в течение определенного периода времени, например, найти. - тип d-mtime 1. Действительно ли это возможно с Вашим синтаксисом? –  Magnus 05.10.2012, 03:55
  • 2
    @Magnus Любое использование find -exec или регистрируйте время for цикл. Просто не пытайтесь проанализировать вывод find или что-либо, что просто печатает имена файлов. –  jw013 05.10.2012, 03:58
  • 3
    Существует ли источник, на который можно указать на оценку, почему это было бы плохой идеей? Я просто попробовал за.. в $ (находят) с 40 000 каталогов, и это, кажется, хорошо работает. именам файлов –  Magnus 05.10.2012, 04:14
  • 4
    Unix позволяют содержать любой символ кроме \0 и /. Подобные вещи являются в основном двоичными блобами и не могут быть надежно проанализированы с помощью вещей как замена команды - слишком много возможных забавных символов, чтобы испортить парсинг. Попробовать mkdir test && cd test && mkdir 'one dir' && for dir in $(find . -type d); do printf '%s\n' "$dir"; done. Необходимо видеть два каталога, one и dir. –  jw013 05.10.2012, 04:19
  • 5
    , в этом суть Вы делали. Однако я управляю точно файлами в этом каталоге, таким образом, я знаю, что они не будут содержать "забавных" символов. Я предполагаю, что мой вопрос был, больше "Будет удар для аварийного завершения цикла, если список находки станет слишком большим". –  Magnus 05.10.2012, 04:29

Если Вы имеете bash 4, можно сделать что-то рекурсивное как:

shopt -s globstar
for dir in **/; do echo "$dir"; done
3
27.01.2020, 23:11

Я не соглашаюсь с ответом, который Вы приняли - Вы столкнетесь с проблемами памяти, если Вы будете использовать $(find), даже без exec существующий.

Вместо этого запишите это как

find . -type d | while IFS= read -r dir
do
  # My code
done

(Примечание: это предполагает, что нет никакого имени каталога, содержащего символ новой строки.)

Затем Вам не будет нужна временная память для хранения find вывод, как Вы были бы с заменой команды. Это также работало бы если find или другая команда никогда не завершалась, например:

# will not work!
for line in $(yes) ; do echo "$line" ; done

# works
yes | while IFS= read -r line ; do echo "$line" ; done
2
27.01.2020, 23:11
  • 1
    Таким образом, Ваше решение выполняет цикл с условием продолжения для каждой строки вывода, как только каждая выходная строка от находки появляется, в то время как мое предварительно вычисляет всю вещь и затем работает за циклом. Если я понимаю вещи правильно. Конечно, находка выложит директоров быстрее, чем цикл с условием продолжения может обработать их, таким образом, это должно было бы все еще буферизовать вывод где-нибудь. –  Magnus 05.10.2012, 15:04
  • 2
    Да, Ваше первое предложение корректно. Для второго, нет, канал заблокируется и так find также заблокируется при записи его вывода. Другими словами, find будет просто ожидать, если цикл не может поддержать на высоком уровне. –  Jim Paris 05.10.2012, 20:19
  • 3
    Ничего себе, это аккуратно. Я даже не знал, что каналы могли заблокироваться. Вы изучаете что-то новое каждый день! Я только что переписал свой сценарий, чтобы сделать это Ваш путь и избежать любой ПУТАНИЦЫ. Я сожалею, что имею только один принятый ответ для предоставления. –  Magnus 05.10.2012, 20:47

Не генерируйте имена файлов с заменой команды: это повредится, если имена файлов будут содержать пробел или \[?*.

С ударом ≥4, ksh93 или zsh, можно избежать большей части использования find то единственное использование -type d или -name … предикаты при помощи ** шарик для соответствия подкаталогам на любой глубине. В ударе, выполненном shopt -s globstar сначала. В ksh, выполненном set -o globstar сначала.

for dir in **/; do …; done

Портативно, или в случаях, где Вам нужен больше, использовать find … -exec … + или find … -print0 | xargs -0 …. Этот подход обладает дополнительным преимуществом выполнения find несколько параллельно с действием с файлами, хотя это только становится верным для огромных деревьев каталогов (по крайней мере, тысячи соответствия файлам). Можно сделать find или xargs выполните оболочку, если необходимо сделать более, чем выполненный одну команду.

find -type d -exec sh -c 'for x in "$@"; do echo "$x"; done' _ {} +

(Это _ $0 в отрывке оболочки, который мы не используем.)

0
27.01.2020, 23:11

Теги

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