Bash – Замена команд добавляет одинарные кавычки

У меня проблема с поведением bash при оценке серьезных акцентов. Я хочу запустить find с дополнительным именем:

find -name "*.log" 

отлично работает, но когда я хочу получить часть -name из вложенного скрипта

 find `echo "-name \"*.log\""` 

он просто не работает. Запуск в bash -x показывает, что эта команда оценивается как

 find -name '"*.log"' 

По-видимому, это из-за этих одиночных кавычек. Есть ли какое-то обходное решение, чтобы избавиться от них? С наилучшими пожеланиями.

// запрашивает версию ОС и bash: Debian, 7.8 wheezy, Bash 4.2.37 (1) -release

One Solution collect form web for “Bash – Замена команд добавляет одинарные кавычки”

Bash не добавил одиночных кавычек в команду. Одиночные кавычки, которые вы видите, добавляются, чтобы сделать отображаемую команду действительной синтаксисом bash. Если ты видишь

 find -name '"*.log"' 

это означает, что bash было сказано выполнить эту команду: find с двумя аргументами -name и "*.log" (двойные кавычки являются частью аргумента). Он мог быть введен точно так же или каким-то другим эквивалентным способом, например

 find -name \"*.log\" find -name "\"*.log\"" find -name '"*.'log""\" 

Теперь давайте посмотрим, что вы написали:

 find `echo "-name \"*.log\""` 

Команда, запущенная в подоболочке,

 echo "-name \"*.log\"" 

Его выход

 -name "*.log" 

Вот откуда берутся двойные кавычки в аргументе. Когда результат подстановки команды интерполируется в командную строку, он не анализируется как синтаксис оболочки – так, например,

 find `echo '; rm -rf ~'` 

не будет удалять все ваши файлы, а вместо этого ; как первый аргумент для find , rm как второй, -rf как третий и ваш домашний каталог (при условии, что он не содержит каких-либо специальных символов) в качестве четвертого.

Когда подстановка переменных или подстановка команд вне двойных кавычек, следующие переменные происходят с значением переменной или выходом команды:

  1. Только для подстановки команд: завершающие символы новой строки разделяются.
  2. Строка разбивается на части, разделенные пробелами. (Вы можете настроить разделители, установив переменную IFS .) Обратите внимание, что результатом этого преобразования является список строк.
  3. Каждый элемент списка интерпретируется как шаблон шаблона. Если этот шаблон совпадает с файлами, то элемент заменяется списком соответствующих файлов (это называется подстановкой ). Если шаблон не соответствует ни одному файлу, элемент остается в покое.

Шаг 2 разбивает строку-имя -name "*.log" на две части: -name и "*.log" . Ни одна часть не соответствует ни одному файлу, поэтому результатом являются два слова – имя и "*.log" .

То, что вы хотели сделать, – это запустить find с аргументами -name и *.log . Вы можете сделать это, отключив глобусы:

 set -f find `echo -name *.log` set +f 

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

  • Я пытаюсь ввести команду в переменную, но сложные случаи всегда терпят неудачу!
  • Почему мой сценарий оболочки задыхается от пробелов или других специальных символов?
Interesting Posts

Emacs: автоматически переключается в режим char при переключении в анси-терминальное окно

Как определить горячую клавишу для приложения, которая отменяет глобальную горячую клавишу?

Как скопировать контекст SELinux из одного каталога и применить его к другому каталогу?

Как использовать rsync с помощью samba share

Как правильно установить Steam на элементарной ОС?

mbsync: переместить вложенные папки в корень

Как управлять разрешением приложения

Создание моей собственной функции cp в bash

Bash-скрипт обрабатывает текст snmp только для печати желаемого идентификатора

Автозапуск Vimrc не работает

копирование файлов из многих каталогов в один с помощью rsync

sysctl: неверная настройка "net.ipv4.ip_local_reserved_ports ="

Как запустить программу C в качестве демона?

Извлечение нескольких экземпляров текста между двумя словами, включая стартовое слово, но исключающее слово

Bash: double равно vs -eq

Linux и Unix - лучшая ОС в мире.