GNU знайти і замаскувати {} для деяких снарядів - що?


34

На головній сторінці пошуку GNU зазначено:

-exec command ;
    [...] The  string `{}'  is  replaced  by the current 
    file name being processed everywhere it occurs in the 
    arguments to the command, not just in arguments where 
    it is alone, as in some  versions  of  find.
    Both  of  these  constructions might need to be escaped 
    (with a `\') or quoted to protect them from expansion 
    by the shell. 

Це від людини до find(GNU findutils) 4.4.2.

Тепер я перевірив це з нахилом і тире, і обом не потрібно, щоб {}маска була замаскована. Ось простий тест:

find /etc -name "hosts" -exec md5sum {} \; 

Чи є оболонка, для якої мені справді потрібно замаскувати брекети? Зауважте, що це не залежить від того, чи вміщений файл містить порожню (викликається з bash):

find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \; 
/home/stefan/Ubuntu One

Це змінюється, якщо знайдений файл передається підпакеті:

find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \; 
ls: cannot access /home/stefan/Ubuntu: No such file or directory
ls: cannot access One: No such file or directory

яку можна вирішити:

find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \;

на відміну від:

find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \; 
/home/stefan/Ubuntu One

але це не те, про що розповідає сторінка людини, чи не так? То яка оболонка трактує {}по-іншому?


@Volker Siegel: Ваша редакція могла відбутися з добрим наміром, але я перевірив свій поточний посібник з пошуку та ваші виправлення неправильні. Ви також упустили можливість підсумувати свої зміни, що є шкідливою звичкою, тому я відкидаю ваші зміни. Вибачте, товариш.
користувач невідомий

О, дякую, що відкотився, якщо щось щось зламало. Я пам’ятав, що компілятор тексту, який генерує формат чоловічої сторінки, використовуваний для створення цих «типографічних лапок», як артефакт визначення візуалізації. Він також може надавати TeX для ідеального форматування друку. Я помітив цитати, тому що вони переплутали виділення синтаксису. Я припустив, що незвична перша цитата неправильна при використанні в коді, і все одно припускаю, що. Зауважте, що дві зміни були в тексті опису, а не в коді. Тож якщо ми розглядаємо їх як типографіку - естетичну візуалізацію - вони праві.
Волкер Зігель

Схоже, що в рендерингу інформації виходить однакова цитата з обох сторін. Без сумніву, моя зміна зробила його відмінним від оригіналу, ви праві. Але це спричинило якісь проблеми? (Я розглядаю першу цитату як помилку в визначенні людини, яка, як я знаю, це єдиний випадок типографії.
Volker Siegel,

Я щойно перевірив: `{} 'не працює в командному рядку. Це технічно правильно, але мені не подобається, що нічого підозрюючий користувач отримує дивну помилку, коли намагається його скопіювати та вставити.
Волкер Зігель

@VolkerSiegel: Це прозовий текст, а не код, і що тут повинен скопіювати користувач? І це цитування довідної сторінки з 2011 року. Я не бачу жодного значення, яке виправляло б уривок, щоб потім вказати, чому я вносив виправлення на сторінку man. Тема досить складна. Якби це було вашим питанням, я б не намагався вас переконати, точно цитувати чоловічу сторінку, але для мого питання я не в настрої робити компроміси. Цитування - цитування.
користувач невідомий

Відповіді:


26

Резюме : Якщо коли-небудь була оболонка, яка розширювалася{} , то це вже справді старі речі.

В оболонці Bourne і POSIX-сумісних оболонки, брекети ( {а }) звичайні символи ( в відміну (та )які є текстовими роздільниками , як ;і &, і , [і ]які Підстановка символів). Наступні рядки повинні бути надруковані буквально:

$ echo { } {} {foo,bar} {1..3}
{ } {} {foo,bar} {1..3}

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

Ksh реалізує розширення дужок як несумісне розширення оболонки Bourne. Це можна вимкнути за допомогою set +B. Bash в цьому відношенні імітує ksh. Zsh реалізує також розширення дужок; там його можна вимкнути за допомогою set +Iабо setopt ignore_bracesабо emulate sh. Жодна з цих оболонок не розширюється {}в будь-якому випадку, навіть коли це підряд слово (наприклад foo{}bar), завдяки загальному використанню в аргументах до findта xargs.

Single Unix v2 зазначає, що

У деяких історичних системах фігурні дужки трактуються як оператори управління. Щоб допомогти в майбутніх заходах зі стандартизації, портативні програми повинні уникати використання дужок без котирування для представлення самих символів. Цілком можливо, що майбутня версія стандарту ISO / IEC 9945-2: 1993 може вимагати цього {і }розглядатись окремо як оператори управління, хоча маркер {}, ймовірно, буде виключенням цього випадку через часто використовувану find {}конструкцію.

Ця примітка була залишена в наступних версіях стандарту; що прикладиfind мають некотируваних використання {}, як це роблять приклади дляxargs . Можливо, були історичні снаряди Борна, де {}їх треба було цитувати, але вони вже були б давно застарілими системами.

Реалізації CSH у мене є під рукою (OpenBSD 4.7, BSD CSH на Debian , Tcsh) все розширення {foo}до , fooале залишити в {}спокої.


1
@geekosaur: У коментарях працює лише невеликий набір відміток . Я не знаю, що ти намагаєшся сказати. Якщо мова йде про розширення брекетів ksh et al, прочитайте мій абзац, починаючи з "Ksh реалізує розширення дужок як несумісне розширення".
Жил "ТАК - перестань бути злим"

2
Це було bash(див. $BASH_VERSION). Розширення брекетів дуже живе і добре.
geekosaur

2
Це був сенс. {}Синтаксис виник в csh, але {}розширено в порожній рядок. Більш нові оболонки визнають, що це безглуздо, але все ж є деякі старі csh.
geekosaur

1
@geekosaur: Чи можете ви сказати, яка конкретна версія csh на якій конкретній платформі? Я вважаю за краще тестувати його сам (якщо це можливо на Linux) або бути впевненим, що людина тестує це сам.
користувач невідомий

1
@geekosaur, поширився {}fooб на foo, але {}розшириться на {}(за винятком випадків, коли в рамках задніх посилань, але цитування не допоможе) і було б задокументовано як таке. Я перевірив це на csh 2BSD (перший реліз), 2.79BSD, 2.8BSD та 2.11BSD.
Стефан Шазелас

12

{}Потрібно бути вказані в версіях fishоболонки До 3.0.0.

$ fish -c 'echo find -exec {} \;'
find -exec  ;

І в оболонці rc (також akangaна основі rc, але не es):

$ rc -c "echo find -exec {} ';'"
line 1: syntax error near '{'

Це, мабуть, не оболонки, про які автори цього GNU знаходили документацію, маючи на увазі, коли вони писали цей текст fish вперше випуску у 2005 році (тоді як цей текст чи подібний вже був у 1994 році) таrc спочатку не був оболонкою Unix.

Ходять чутки, що деякі версії csh(оболонки, що запровадили розширення дужок) вимагають цього. Але важко надати кредит тим, з моменту першого виходу cshв 2BSD. Ось як перевірено в емуляторі PDP11:

# echo find -exec {} \;
find -exec {} ;

А на сторінці чоловіка з 2BSD cshчітко зазначено :

Як особливий випадок `{',`}' та `{} передаються безперешкодно.

Тож я вважаю це дуже дивним, якби пізніша версія csh чи tcsh пізніше зламала це.

У деяких версіях це могло обійти деякі помилки. Ще з тим 2BSD csh (те саме в 2.79BSD, 2.8BSD, 2.11BSD):

# csh -x
# echo foo {} bar
echo foo {} bar
foo {} bar
# echo `echo foo {} bar`
echo `echo foo {} bar`
echo foo {} bar
foo  bar

Цитування не допомагає, хоча:

# echo `echo foo '{}' bar`
echo `echo foo '{}' bar`
echo foo {} bar
foo  bar

Ви можете процитувати всю заміну команди:

# echo "`echo foo {} bar`"
echo `echo foo {} bar`
echo foo {} bar
foo {} bar

Але це передає один аргумент на те зовнішнє відлуння.

У cshабо tcshвам потрібно буде цитувати те, {}коли не самостійно, як у:

find . -name '*.txt' -type f -exec cp {} '{}.back' \;

(хоча таке findвикористання не є портативним, оскільки деякі findз них розширюються лише {}тоді, коли вони є самостійними).


1

Одним словом, csh. bashта інші сучасні оболонки визнають, що користувач, ймовірно, не вимагає розширення нульової дужки. (Модерн cshє насправді tcshі до цього часу також може справлятися з {}розумом.)


Приємно чути, але я прошу навпаки, оболонка для якої не справляється з цим сумлінно.
користувач невідомий

Ви припускаєте, що хтось зайде і вирве посилання інформаційної сторінки на додаткове цитування лише тому, що в усіх системах Linux новіші csh. Не всі працюють утиліти GNU на Linux; насправді досить часто їх встановлювати на старих комерційних системах Unix, пакетних команд яких обмежено. (Заміна cshцих систем є менш імовірною, оскільки системні скрипти можуть покладатися на ідіосинкразії оригіналу csh, і навіть якщо всі користувачі налаштовані використовувати новішу csh, rootмайже напевно потрібно залишатись у комплекті з версією.)
geekosaur

2
Ні. Я дебатую з хлопцем, який каже, що у нашій вікі ми повинні давати поради весь час користуватися "{}", тому що така сторінка "man" говорить. І тепер я хотів би знати, чи є оболонка, яку я не використовую, як-от ksh, zsh, tcsh, csh або XYZsh, яку я не знаю, для якої ця заява правдива, чи я, чесно кажу, можу припустити, що там немає. Якщо є оболонки для різних Unixes, яким потрібен "{}", це було б прекрасним поясненням того, чому речення все ще знаходиться на сторінці "man", але не підходить як порада для початківців Linux.
користувач невідомий

Тепер мені цікаво , якщо pdkshробить правильну річ ... хоча правильна відповідь , що , ймовірно , «реальним kshє FOSS в ці дні».
geekosaur

4
Pdksh, як mksh, ksh93, bash і zsh, розширює дужки лише тоді, коли між ними є кома (або ..для ksh93, bash і zsh). Тільки (t) csh розширюється {foo}до foo, і навіть він залишає в {}спокої (принаймні, на останніх BSD).
Жил 'ТАК - перестань бути злим'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.