Використання тире (-) замість імені файлу


110

Для команди, якщо використання -в якості аргументу замість імені файлу буде означати STDIN або STDOUT.

  1. Але в цьому прикладі він створює файл з назвою -:

    echo hello > -

    Як я можу зробити -в цьому прикладі значення STDOUT?

  2. І навпаки, як я можу -означати файл, названий -у таких прикладах, як:

    cat -

3
Оскільки я, мабуть, повинен мати 50 репутацій, щоб коментувати безпосередньо ... Щодо коментаря / dev / stdin / dev / stdout, AIX, який є законною похідною UNIX, не має цих псевдопристроїв. І, як додатковий коментар, LINUX не є похідною UNIX ні в якому разі. Це сумісна з POSIX технологія роботи і найпопулярніша з цих операційних систем UNIX на даний момент, але не помиляйтесь, це не UNIX. Але суть відповідей тут правильна. Позначення "-" не інтерпретується оболонкою як особливе, і тому передається безпосередньо кожній окремій програмі як ARG. Якщо додаток не розпізнає

Також є 2>&-конструкція, що означає «близький дескриптор 2».
користувач3132194

@ user95873, я вважаю, що ви хотіли сказати: хоча Linux є Unix-подібним, не кожен Unix-подібний (або справжній UNIX) є Linux . Незалежно від того, Linux чи не справжній UNIX (тобто відповідає Єдиній специфікації UNIX), не має відношення до проблеми / dev / std {in, out, err}. Як / dev / std {in, out, err} додана функція, не пропущена .
саша

Відповіді:


156

Використання -як імені файлу для позначення stdin / stdout - це умова, якою використовується багато програм. Це не особлива властивість імені файлу. Ядро не розпізнається -як особливе, тому будь-які системні виклики, що посилаються на -ім'я файлу, будуть використовуватись -буквально як ім'я файлу.

З перенаправленням bash -не розпізнається як спеціальне ім'я файлу, тому bash використовуватиме це як буквальне ім'я файлу.

Коли catрядок бачить -як ім'я файлу, він трактує його як синонім stdin. Щоб обійти це, потрібно змінити рядок, який catбачить таким чином, щоб він все ще посилався на файл, який називається -. Звичайний спосіб зробити це - префіксація імені файлу шляхом - ./-або /home/Tim/-. Ця методика також використовується для вирішення подібних проблем, коли параметри командного рядка зіштовхуються з іменами файлів, тому файл, згаданий як ./-e, не відображається, наприклад, як -eкомандний рядок для програми.


37
Варто додати , що /dev/stdinі /dev/stdoutповсюдно доступні і можуть бути використані замість -конвенції.
jmtd

Також у catвипадку використання перенаправлення замість переліку аргументу може допомогти cat <-:; однак, було б важко змішати і співставити це з об'єднанням декількох файлів одночасно.
jmtd

10
@jmtd: / dev / std {in, out} не доступні повсюдно. Не всі Unix мають його.
camh

2
Цікаво, що я припускав, що вони є частиною POSIX (але не можу підтвердити). Вони присутні принаймні на Linux, BSD та Solaris. Чи можете ви навести приклад сучасного UNIX, який їм не вистачає?
jmtd

1
@camh Не впевнений, чи отримали ви це повідомлення, і це дуже, дуже стара тема; Я не впевнений, чи зможете ви, але мені дуже цікаво, чи знаєте ви відповідь на jmtdзапитання? :)
Поворот

18
  1. Замість цього echo hello > -можна використовувати echo hello > /dev/stdout.

    Хоча '-' - це умова, яку має реалізовувати кожна програма, яка хоче її підтримати /dev/stdin, /dev/stdoutі /dev/stderrвони, коли підтримуються ОС (принаймні, Solaris, Linux та BSDs), не залежать від програми та працюватимуть як ви мають намір.


9

Як згадується Кемх , -це лише конвенція про іменування, яка використовується деякими програмами. Якщо ви хочете звернутися до цих потоків за допомогою дескриптора файлу, який оболонка розпізнає, jiliagre вірно використовував ім'я /dev/stdinабо /dev/stdoutзамість цього. Ці імена файлів повинні працювати в будь-якому місці, де нормальне ім'я файлу буде працювати.

  1. Як сказано, ваш перший приклад - це щось дурне. Будь-який вихід, який би потрапив оператор переадресації для запису у файл, вже є стандартним висновком ON, тому перенаправлення та записування його назад, звідки він прийшов, є марним. Поведінка, якою ви користуєтесь там, є думкою, а не перенаправленням:

    echo hello |
  2. У вашому другому прикладі вам просто потрібно навести певну ознаку того, що ви хочете літтеральний файл цього імені, а не внутрішній псевдонім, який він має. Зробити це найпростіше, вказавши шлях до файлу таким чином:

    cat ./-

6

Щодо 1, програма має його підтримувати. Ви не можете просто довільно ним користуватися. Що стосується 2, введення переадресації з (наприклад, cat < -).


1

Підхід "-" має багато проблем. Перш за все, це вимагає інтерпретації символу "-", і багато програм не виконують такого тлумачення. Крім того, існують деякі програми, які інтерпретують дефіс як роздільник, що позначає кінець параметрів командного рядка. Програми написані для роботи з аргументами імен файлів, підхід '-' - хакер, хороший, але слабкий.

Найкращий спосіб:

$ echo hello > /dev/fd/1

/dev/stdout є символьним символом зв'язку /dev/fd/1


Перенаправлення інтерпретується оболонкою, а не програмою, що викликається.
sherrellbc
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.