Почему команды cat, grep и другие команды не могут понять файлы, начинающиеся с знака «минус»?

Если у меня есть файл, имя которого начинается с одного или нескольких знаков минус, например, --1 он не может использоваться как параметр для многих команд. Даже если я бегу

 cat --1 

вместо содержимого файла я получаю нераспознанное сообщение об ошибке опции:

 cat: unrecognized option '--1' 

Тот же эффект появляется при вводе

 cat "--1" cat '--1' cat \-\-1 

ничего не работает. Файлы, начинающиеся с '-', не являются незаконными в файловой системе, но работать с ними в cli и скриптах довольно сложно. Хорошо, в случае cat или grep я могу использовать

 cat <--1 

и это будет работать, но

 rm --1 

тоже не будет работать, и довольно сложно подставить эту команду чем-то другим. Очень неудобно в конце концов. Существует ли универсальное обходное решение, отличное от того, чтобы не использовать такие имена файлов?

BTW, если файл имен один - и все большинство команд поймут его как stdin , не так ли?

И было бы трудно не использовать такие имена файлов, так как я не могу переименовать их все в скрипте, используя команду mv .

  • Можно ли использовать утилиту Rename для упрощения этого скрипта, который использует Find и Mv?
  • Продолжить команды оболочки после подключения к SSH
  • Bash: Как читать по одной строке за один раз из вывода команды?
  • Чтобы добавить номера строк в каждой строке с помощью команды оболочки?
  • Попытка выйти из сценария с кодом состояния, но получить «неожиданный конец файла»,
  • Как форматировать десятичное число, чтобы отображать прецизионные ноль, но не конечные?
  • Получить файлы с именем, содержащим значение даты, меньшее или равное заданной дате ввода
  • Объясните команду оболочки: shift $ (($ optind - 1))
  • 4 Solutions collect form web for “Почему команды cat, grep и другие команды не могут понять файлы, начинающиеся с знака «минус»?”

    Соглашение состоит в том, что все, что начинается с a, - это вариант. Это сталкивается с именами файлов, которые начинаются с - . Чтобы обойти это, большинство команд распознают -- как дозорный пункт конца опций. Все после -- не будут распознаваться как опции, а будут восприниматься буквально как имена файлов.

    Например

     cat -- --1 

    или

     rm -rf -- --1 

    Другой метод – определить имя файла с помощью пути.

    например

     cat ./--1 

    или даже

     cat /home/username/foo/--1 

    Лучше всего никогда не создавать имена файлов, которые начинаются с - . Имена файлов могут содержать все виды символов, включая новую строку, но только потому, что это возможно, это не значит, что вы должны это делать.

    Чтобы ответить на ваш вопрос: почему команды cat, grep и другие команды не могут понять файлы, начинающиеся с знака «минус»? Потому что командная строка – это просто строка. Оболочка делает некоторое расширение имени файла и некоторое разбиение слов и замену переменных, но в конце программа получает массив строк.

    Как вы отделяете строки, которые означают опции из строк, которые означают имена файлов? Некоторыми дозорными персонажами. Соглашение в мире unix / linux должно использовать - как персонаж дозорного. Все, что начинается с - это вариант. Ну, почти все. Аргументы для параметров также могут начинаться с - , но это детали отдельной программы.

    Не каждая программа соответствует этому соглашению. Вероятно, самым популярным примером является dd :

     dd if=/dev/random of=whatfreespace 

    dd распознает имена файлов, потому что они появляются после знака = .

    Большинство, если не все, программы GNU соответствуют GNU getopt конвенции: короткие параметры начинаются с - и только один символ, длинные варианты начинаются с -- и имеют как минимум два символа. -- по собственному значению конец опций и все строки после этого знака не распознаются как опции. Для получения более подробной информации ознакомьтесь с инструкциями синтаксиса аргументов программы в руководстве GNU libc.

    Один пример программы, которая только частично соответствует конвенции GNU, find :

     find -not -name porn -delete 

    Хотя find использует - чтобы отличать опции от не-опций, он не отличается длинными опциями из коротких опций. Он распознает -- как конец опций. Каждая программа может определить свой собственный способ распознавания опций и имен файлов и всего остального.

    Соглашение об интерпретации единственного - как stdin – это просто соглашение о том, как интерпретировать односимвольный символ, когда он встречается в массиве строк.

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

     cat ./--filename 

    Использование cat -- --filename указывает на прекращение поиска любой опции. Есть потенциальные проблемы с этим подходом, поскольку сторонние приложения не знают, как обрабатывать имена разбитых файлов. Однако двоичные файлы POSIX, такие как cp, rm, cat т. Д., Знают, как обрабатывать эти тире

    В более общем плане это:

     cat $options_and_or_file_patterns_or_stdin_if_dash cat "$option_or_file_or_stdin_if_dash" cat -- "$file_or_stdin_if_dash" cat < "$file" cat - < "$file" # same as above 
    Linux и Unix - лучшая ОС в мире.