Зупинити розширення символів узагальнюючої оболонки?


88

Чи є спосіб скомпільованої програми командного рядка повідомити bash або csh, що вона не хоче розширювати символи підстановки у своїх параметрах?

Наприклад, може знадобитися така команда оболонки, як:

foo *

просто повернути числове значення ASCII цього символу.

Відповіді:


119

Ні. Розширення відбувається до фактичного запуску команди.
Ви можете вимкнути глобус лише перед запуском команди або цитуванням зірки.

$ # quote it
$ foo '*'

$ # or escape it
$ foo \*

$ # or disable the glob (noglob)
$ set -f
$ foo *

$ # alternative to set -f
$ set -o noglob
$ # undo it by 
$ set +o noglob

3
також, якщо немає чого розширювати, немає розширення. тобто з порожнім pwd, echo *просто*
sam boosalis

7
@sam Це насправді залежить від того, як встановлені ваші параметри. З tldp: "Якщо не знайдено відповідних імен файлів, а опція оболонки nullglobвідключена, слово залишається незмінним. Якщо nullglobпараметр встановлений, а збігів не знайдено, слово видаляється."
Кріс Міддлтон

дякую, я повинен був визнати, що це було лише з спостереження, а не з будь-якого розуміння.
sam boosalis

@ c00kiemon5ter Як скасувати set -f? Це так unset -f?
Nam G VU

1
@NamGVUset +f
Yngvar Kristiansen

62

Хоча це правда, сама команда не може вимкнути глобалізацію, користувач може сказати оболонці Unix не глобулювати певну команду. Зазвичай це досягається редагуванням файлів конфігурації оболонки. Припускаючи, що команду fooможна знайти на шляху до команди, до відповідного конфігураційного файлу потрібно додати наступне:

Для оболонок sh, bash і ksh:

alias foo='set -f;foo';foo(){ command foo "$@";set +f;}

Для оболонок csh та tcsh:

alias foo 'set noglob;\foo \!*;unset noglob'

Для оболонки zsh:

alias foo='noglob foo'

Шлях команди використовувати не потрібно. Скажімо, команда foo зберігається в каталозі ~ / bin, тоді вищезазначене стане:

Для оболонок sh, bash і ksh:

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

Для оболонок csh та tcsh:

alias foo 'set noglob;$home/bin/foo \!*;unset noglob'

Для оболонки zsh:

alias foo='noglob ~/bin/foo'

Все вищеперелічене було протестовано за допомогою OSX 10.9.2 від Apple. Примітка: Під час копіювання наведеного коду будьте обережні, видаляючи пробіли. Вони можуть бути значними.

Оновлення:

Користувач geira зазначав, що у випадку з оболонкою bash

alias foo='set -f;foo';foo(){ ~/bin/foo "$@";set +f;}

можна замінити на

reset_expansion(){ CMD="$1";shift;$CMD "$@";set +f;}
alias foo='set -f;reset_expansion ~/bin/foo'

що виключає необхідність функції foo.

Деякі веб-сайти, використовувані для створення цього документа:


3
Це мала бути прийнята відповідь, оскільки це доводить, що дійсно можливо робити те, що хоче ОП. Для деяких ще кращих методів у bash, це посилання задокументує різні варіанти: blog.edwards-research.com/2011/05/preventing-globbing
geira

@geira: Іноді відповідь приймається до того, як буде опублікована краща відповідь. Я вважаю, що це може бути одним із таких випадків. Я також вірю, що знаки відповіді, оскільки більшість корисних для користувачів спочатку опиняються. Примітка. Я додав ваші дані до своєї відповіді.
Девід Андерсон,

@geira, OP хоче, щоб скомпільована програма обмінювалася даними з оболонкою; відповідь, що можна налаштувати оболонку так, щоб вона поводилась за бажанням за принципом команди, є корисною відповіддю, і я б сам прийняв цю, але я бачу місце для незгоди щодо того, чи вона повністю актуальна.
Чарльз Даффі

Той факт, що це можна зробити, не означає, що це слід робити. Зміна поведінки оболонки з розумних очікувань користувача на вибрані команди звучить дивно і в кінцевому підсумку небажано.
триплі

@tripleee: Був час, коли люди очікували реле та вакуумних трубок. Очікувались отвори, пробиті в картонних картках та паперовій стрічці. Люди тримали правила слайдів замість калькуляторів та телефонів. Я думаю, для вас це було б бажаним. Мені було мало до тих часів. Мені подобається бачити, що буде далі.
Девід Андерсон,

8

Розширення виконується оболонкою перед запуском програми. Ваша програма не знає, відбулося розширення чи ні.

   set -o noglob

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

Альтернатива - цитувати ваші аргументи, наприклад

foo "*"

4
setopt видається командою, специфічною для zsh. Як говорив інший плакат, для bash ви використовуєте, set -o noglobщоб вимкнути розширення підстановних знаків.
Віраван Пурванто

Зараз внесено зміни. Дякую
Брайан Егнью

1

Обережно: якщо немає імен, що відповідають масці, bash передає аргумент як є, без розширення!

Доказ (pa.py - це дуже простий скрипт, який просто друкує свої аргументи):

 $ ls
f1.cc  f2.cc  pa.py
 $ ./pa.py *.cc
['./pa.py', 'f1.cc', 'f2.cc']
 $ ./pa.py *.cpp
['./pa.py', '*.cpp']

3
Не завжди. set -o nullglobабо shopt -s failglob, і ця поведінка зміниться (двома дуже різними способами).
Чарльз Даффі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.