Чому `sort <“ $ f1 ”` віддається перевазі над `sort -“ $ f1 ”`, і чому це віддається перевагу над `sort“ $ f1 ”`?


29

З /unix//a/458074/674

Не забудьте використовувати -- при передачі довільних аргументів командам (або використовувати перенаправлення, де це можливо). Так sort -- "$f1"або краще sort < "$f1"замість sort "$f1".

Чому перевагу використовувати --та перенаправляти?

Чому sort < "$f1"віддається перевага sort -- "$f1"?

Чому sort -- "$f1"віддається перевага sort "$f1"?

Спасибі.


Відповіді:


55
sort "$f1"

не відповідає значенням, $f1що починається з -або тут для випадку sortдеяких, які починаються з +(може мати серйозні наслідки для файлу, який називається, -o/etc/passwdнаприклад).

sort -- "$f1"

(де -- сигнали закінчуються параметрами) вирішує більшість цих проблем, але все-таки не вдається для файлу, який називається -(який sortінтерпретує замість нього stdin).

sort < "$f1"

Не має цих проблем.

Тут файл відкриває файл оболонки. Це також означає, що якщо файл неможливо відкрити, ви також отримаєте потенційно більш корисне повідомлення про помилку (наприклад, у більшості оболонок буде вказано номер рядка в сценарії), і повідомлення про помилку буде відповідне, якщо ви використовуєте де можливо, переадресації для відкриття файлів.

І в

sort < "$f1" > out

(всупереч sort -- "$f1" > out), якщо "$f1"їх не можна відкрити, outне буде створено / усічено і sortнавіть не буде запущено.

Щоб очистити певну можливу плутанину (наступні коментарі нижче), це не заважає команді інгібувати mmap()файл або lseek()входити всередину нього (не те, що sortце робить), за умови пошуку самого файлу. Єдина відмінність полягає в тому, що файл відкривається раніше, а в дескрипторі 0 файлом оболонкою, на відміну від команди, можливо, в іншому дескрипторі файлу. Команда все ще може шукати / mmap, що fd 0, як заманеться. Це не слід плутати з тим, cat file | cmdде cmdstdin цього разу - це труба, яку неможливо змінити / шукати.


4
Пам'ятайте лише, що використання перенаправлення змушує sortчитати дані послідовно, і ви не можете mmapфайл. Незважаючи на те, що з цим sortможе бути не так багато проблем, врахуйте ефективність роботи less <fileта less file. У першому випадку lessповинен зберігати весь вміст файлу в пам'яті, у другому випадку дозволено читати лише ті частини, які він хоче. А тепер уявіть, що fileце файл журналу на 100 Гб ...
пінопласт летить

7
@styrofoamfly: Це правильно, що less <fileзберігає весь файл у пам’яті, але це не змушене, це недолік менше. Тільки cat file | lessзмушений. Перевірте less /dev/fd/0 <f, що не зберігає файл у пам'яті, навіть якщо він отримує його на stdin. Загальна помилка, що stdin в Unix неможливо побачити. Це може бути видно, залежно від типу файлу.
пт

@styrofoamfly Ви маєте на увазі, що read()читаєте дані послідовно з файлу, при цьому mmap()читайте весь файл в пам'яті відразу?
Тім

1
@JohnBollinger Ні. Це датується щонайменше назад, як getopt від SysIII в 1980 році до початку проекту GNU, і його потрібно підтримувати для більшості стандартних утиліт, включаючи sortPOSIX. Але це правда, що це не завжди підтримується.
Стефан Шазелас

2
Мої вибачення, @ StéphaneChazelas, ви праві щодо походження конвенції, і я ще більше зазначаю, що специфікація POSIX для функції getopt()C визнає цю значимість аргументу --. Але головний момент - це те, що ви приймаєте: обробка аргументів - це область окремих програм, і не всі трактуються --спеціально.
Джон Боллінгер

17

Проблема - назви файлів, що починаються з тире. sort "$f1"не працює, якщо значення f1починається з, -тому що команда буде інтерпретувати значення як опцію. Зазвичай це призводить до помилки, але це навіть може спричинити загрозу в безпеці . З sort -- "$f1", аргумент подвійного тире --означає "немає варіантів поза цією точкою", тому значення f1не буде інтерпретуватися як опція. Але є ще один крайній випадок: якщо значення f1- тире і нічого іншого, то це не варіант, це аргумент -, що означає «стандартний вхід» (тому що аргумент - це вхідний файл; для вихідного файлу це означатиме «стандартний вихід»).

Використання перенаправлення дозволяє уникнути всіх цих підводних каменів.

Це стосується більшості команд, а не тільки sort.


Ви говорите, що sort < "$f1"це спрацювало, якби значення було рівним -? Немає в жодній оболонці, яку я пробував.
grawity

@grawity, порівняйте seq 10 > -; sort -з seq 10 > -; sort < -.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.