Если проверка на соответствие ARG_MAX и количеству файлов в каталоге - PullRequest
0 голосов
/ 16 апреля 2020

У меня есть потенциально большое количество сгенерированных файлов и подкаталогов в каталоге, для которого число не известно до выполнения. Для простоты, скажем, я просто хочу вызвать

mv * /another_dir/.

Но для большого количества файлов и подкаталогов он вернется со страшным «аргументом слишком длинным». Да, я знаю, найти и Xargs это способ справиться с этим. Но я хочу проверить это число на ARG_MAX и попробовать его сначала.

Я нахожусь на Ма c и поэтому не могу поднять настройку ulimit.

Пока что У меня есть

# max_value
if ((expr `getconf ARG_MAX` - `env|wc -c` - `env|wc -l` \* 4 - 2048)  ) ; then echo "ok" ; fi

, который предлагает мне значение для проверки.

Допустим, мое значение теста для вычисления количества файлов или подкаталогов в каталоге основано на

# test_value
(find . -maxdepth 1 | wc -l)

Как я могу получить рабочее выражение независимо от того, сколько файлов

if (test_value < max_value ) ; then echo "do this" else echo "do that" ; fi 

Каждый раз, когда я пытаюсь создать тест if, синтаксис по какой-то причине терпит неудачу при попытке установить параметры max_value и test_value, а затем проверить их вместе. Благодарен за помощь.

1 Ответ

1 голос
/ 16 апреля 2020

При написании сценариев оболочки вы должны уделять много внимания тому, в каком контексте вы находитесь, и использовать правильный синтаксис для этого контекста. То, что находится между if и then, рассматривается как команда, поэтому вы можете использовать, например, if expr 2 \> 1; then. Но современной заменой команды expr является выражение (( )) arithmeti c, поэтому вы должны использовать if (( 2 > 1 )); then. Обратите внимание, что вам не нужно экранировать >, потому что он больше не является частью обычной команды, и что вы не можете поставить пробелы в скобках ( ( something ) ) делает что-то совершенно отличное от (( something )).

(( )) позволяет выполнить расчет / сравнение / et c, как если бы это была команда. Также распространено желание использовать результат вычисления как часть команды; для этого используйте $(( )):

max_value=$(($(getconf ARG_MAX) - $(env|wc -c) - $(env|wc -l) * 4 - 2048))
test_value=$(ls -A | wc -l)

Обратите внимание, что я использовал $( ) вместо обратных галочек; он делает то же самое с несколько более чистым синтаксисом. И снова, расположение скобок имеет значение: $(( )) делает расчет и фиксирует его результат; $( ) запускает команду и фиксирует ее вывод. И $( ( ) ) будет запускать команду в бессмысленной суб-оболочке и записывать ее вывод. О, и я использовал ls -A, потому что find . -maxdepth 1 будет включать в свой вывод . (текущий каталог), давая избыточный счет 1. (И обе версии find и ls будут пересчитывать файлы с переводами строк в их имя; о, хорошо.)

Затем, чтобы сделать окончательное сравнение:

if ((test_value < max_value)) ; then echo "do this" else echo "do that" ; fi 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...