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

Что мешает du выводить размер подпапок, так это аргумент -s (сокращение от --summarize ), который позволяет du выводить только размер его аргументов, а не включать подпапки.

Попробуйте du -hc/.

-121--289304-

Я нашел ответ, и исправление заключается в вводе следующего в командной строке администратора, предполагая, что disk 0 является C: и partition 2 является рассматриваемым разделом.

Введите «diskpart» и нажмите Enter Выполните следующие команды для расширения раздела:

SELECT DISK 0
SELECT PARTITION 2
EXTEND FILESYSTEM
EXIT

-121--289303-

В большинстве языковых стандартов cal использует версию григорианского календаря, используемую Британией и её колониями, которая включает 11-дневный разрыв в сентябре 1752 . Как говорится на справочной странице V7 :

Календарь производится для Англии и её колоний.

Попробуйте сентябрь 1752 года.

Так что даты до этого времени могут не приходиться на будни можно ожидать от экстраполяции современного календаря.

Если используется gcal , можно задать опцию -gregorian-reform для установки даты и продолжительности разрыва.

9
07.05.2018, 17:06
7 ответов

Одинарные кавычки здесь не работают, так как тогда ваша переменная не будет раскрыта. Если вы уверены, что переменная для вашего пути очищена, самое простое решение — просто добавить кавычки вокруг полученного расширения, как только оно появится в новой оболочке bash:

sudo bash -c "cd \"$myvar\""
-2
27.01.2020, 20:04

Нет разбиения слов (, как в функции, которая разбивает переменные при раскрытии без кавычек )в этом коде, поскольку $myvarне заключен в кавычки.

Однако существует уязвимость, связанная с внедрением команд, поскольку $myvarрасширяется перед передачей в bash. Таким образом, его содержимое интерпретируется как код bash!

Пробелы в нем вызовут передачу нескольких аргументов в cdне из-за разбиения слов , а потому, что они будут проанализированы как несколько токенов в синтаксисе оболочки. При значении bye;rebootпроизойдет перезагрузка!¹

Вот вам бы:

sudo bash -c 'cd -P -- "$1"' bash "$myvar"

(где вы передаете содержимое $myvarв качестве первого аргумента этого встроенного скрипта; обратите внимание, как $myvarи $1были заключены в кавычки для соответствующей оболочки, чтобы предотвратить разбиение IFS -слова -(и подстановку )).

Или:

sudo MYVAR="$myvar" bash -c 'cd -P -- "$MYVAR"'

(где вы передаете содержимое $myvarв переменную окружения ).

Конечно, вы не добьетесь ничего полезного, запустив толькоcdво встроенном скрипте (, кроме как проверив, может ли rootcdтуда ). Предположительно, вы хотите, чтобы этот скрипт cdтут же делал что-то еще, например:

sudo bash -c 'cd -P -- "$1" && do-something' bash "$myvar"

Если намерение состояло в том, чтобы использовать sudo, чтобы иметь возможность cdв каталог, к которому у вас иначе нет доступа, то это не может работать.

sudo sh -c 'cd -P -- "$1" && exec bash' sh "$myvar"

запустит интерактивный bashс текущим каталогом в $myvar. Но эта оболочка будет работать как root.

Вы могли бы сделать:

sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"

Чтобы получить непривилегированный интерактив bashс текущим каталогом $myvar,но если у вас изначально не было прав доступа cdк этому каталогу, вы не сможете ничего делать в этом каталоге, даже если это ваш текущий рабочий каталог.

$ myvar=/var/spool/cron/crontabs
$ sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash-4.4$ ls
ls: cannot open directory '.': Permission denied

Исключением будет, если у вас есть разрешение на поиск в самом каталоге, но не в одном из компонентов каталога его пути:

$ myvar=1/2
$ mkdir -p "$myvar"
$ chmod 0 1
$ cd 1/2
cd: permission denied: 1/2
$ sudo sh -c 'cd -P -- "$1" && exec sudo -u "$SUDO_USER" bash' sh "$myvar"
bash-4.4$ pwd
/home/stephane/1/2
bash-4.4$ mkdir 3
bash-4.4$ ls
3
bash-4.4$ cd "$PWD"
bash: cd: /home/stephane/1/2: Permission denied

¹ Строго говоря, для значений $myvar, таких как$(seq 10)(буквально ), при расширении этой подстановки команд оболочкой bash, запускаемой как root

, будет происходить разбиение слов.
13
27.01.2020, 20:04

Прежде всего, как уже отмечали другие, ваша команда cdбесполезна, так как это происходит в контексте оболочки, которая немедленно завершает работу. Но в целом вопрос имеет смысл. Что вам нужно, так это способ заключать в кавычки произвольную строку , чтобы ее можно было использовать в контексте, где она будет интерпретироваться как строка -в кавычках. У меня есть пример этого на моей странице sh трюки :

.
quote () { printf %s\\n "$1" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/'/" ; }

С помощью этой функции вы можете:

myvar="/path to/my directory"
sudo bash -c "cd $(quote "$myvar")"
3
27.01.2020, 20:04

То, что предлагает Стефан Шазела, определенно лучший способ сделать это. Я просто дам ответ о том, как безопасно цитировать синтаксис расширения параметра, а не использовать подпроцесс sed, как в ответе R...

myvar='foo \'\''"bar'

quote() {
  printf "'%s'" "${1//\'/\'\\\'\'}"
}

printf "value: %s\n" "$myvar"
printf "quoted: %s\n" "$(quote "$myvar")"
bash -c "printf 'interpolated in subshell script: %s\n' $(quote "$myvar")"

Вывод этого скрипта::

value: foo \'"bar
quoted: 'foo \'\''"bar'
interpolated in subshell script: foo \'"bar
3
27.01.2020, 20:04

Существует новый (bash 4.4 )магия цитирования, которая позволяет вам более прямо делать то, что вы хотите. В зависимости от более широкого контекста использование одного из других методов может быть лучше, но в этом ограниченном контексте он работает.

sudo bash -c "cd ${myvar@Q}; pwd"
4
27.01.2020, 20:04

Да, есть разделение слов.
Ну, технически, разделение командной строки при разборе строки bash.

Давайте сначала правильно цитируем:

Самое простое (и небезопасное )решение, позволяющее заставить команду работать так, как вы, как я полагаю, захотите, это:

bash -c "cd \"$myvar\""

Давайте подтвердим, что происходит (, предположивmyvar="/path to/my directory"):

$ bash -c "printf '<%s>\n' $myvar"
<./path>
<to/my>
<directory>

Как видите, строка пути была разбита на пробелы. И:

$ bash -c "printf '<%s>\n' \"$myvar\""
<./path to/my directory>

Не разделен.

Однако команда (в том виде, в каком она написана ), небезопасна. Лучшее использование:

$ bash -c "cd -P -- \"$myvar\"; pwd"
/home/user/temp/path to/my directory

Это защитит cd от файлов, начинающихся с тире (-), или от перехода по ссылкам, которые могут привести к проблемам.

Это будет работать, если вы можете быть уверены, что строка в $myvarявляется путем.
Однако «внедрение кода» по-прежнему возможно, поскольку вы «выполняете строку» :

.
$ myvar='./path to/my directory";date;"true'
$ bash -c "printf '<%s> ' \"$myvar\"; echo"
<./path to/my directory> Tue May  8 12:25:51 UTC 2018

Вам нужно более сильное цитирование строки, например:

$ bash -c 'printf "<%s> " "$1"; echo' _ "$myvar"
<./path to/my directory";date -u;"true>

Как вы можете видеть выше, значение не интерпретировалось, а просто использовалось как "$1'.

Теперь мы можем (безопасно )использовать sudo:

$ sudo bash -c 'cd -P -- "$1"; pwd' _ "$myvar"
_: line 0: cd:./path to/my directory";date -u;"true: No such file or directory

Если аргументов несколько, можно использовать:

$ sudo bash -c 'printf "<%s>" "$@"' _ "$val1" "$val2" "$val3"
1
27.01.2020, 20:04

IFSне влияет на разделение чтения, а только на разделение расширения, поэтому вы можете просто отключить разделение слов на уровне выполнения, а не играть в игры с цитированием, чтобы танцевать вокруг него.


Чтобы заставить подоболочку sudo сделать это, передайте переменную в ее окружение (обратите внимание на одинарные кавычки здесь):

myvar=$HOME/'my quirky path'
myvar=$myvar sudo -E bash -c 'IFS=; cd $myvar; pwd'

или

sudo myvar="$myvar" bash -c 'IFS=; cd $myvar;pwd'

но обычно это не так неуклюже, когда вы не пытаетесь пробить несколько слоев, синтаксис оболочки для этого более разумен, и видя назначение IFS впереди, успокаивает желание одержимо проверять цитирование безопасности:

(IFS=; sudo frob $myfile)

или

myfunc() { local IFS=; sudo frob $1; }

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

date=`date` somecommand
1
09.08.2020, 19:12

Теги

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