Si su administrador de archivos muestra el dispositivo, ya está montado. Intente desmontar el dispositivo a través del administrador de archivos y vuelva a ejecutar jmtpfs /media/mobile.
2 команды не эквивалентны :учитывать обработку ошибок:
cat <file that doesn't exist> | less
создаст пустой поток, который будет передан в конвейерную программу... таким образом, вы получите дисплей, на котором ничего не отображается.
< <file that doesn't exist> less
не сможет открыть бар, а затем вообще не откроет меньше.
Попытка изменить первое на второе может привести к поломке любого количества сценариев, ожидающих запуска программы с потенциально пустыми входными данными.
«Бесполезное использование cat
» больше относится к тому, как вы пишете свой код, чем к тому, что на самом деле запускается при выполнении сценария. Это своего рода дизайн против -шаблона , способ сделать то, что, вероятно, можно было бы сделать более эффективным образом. Это провал в понимании того, как лучше всего комбинировать данные инструменты для создания нового инструмента. Я бы сказал, что объединение нескольких команд sed
и/или awk
вместе в конвейер также иногда можно назвать признаком того же анти--паттерна.
Исправление экземпляров «бесполезного использования cat
» в скрипте — это в первую очередь вопрос исправления исходного кода скрипта вручную. В этом может помочь такой инструмент, как ShellCheck , указывающий на очевидные случаи:
$ cat script.sh
#!/bin/sh
cat file | cat
$ shellcheck script.sh
In script.sh line 2:
cat file | cat
^-- SC2002: Useless cat. Consider 'cmd < file |..' or 'cmd file |..' instead.
Было бы сложно заставить оболочку делать это автоматически из-за особенностей сценариев оболочки. Способ выполнения сценария зависит от среды, унаследованной от его родительского процесса, и от конкретной реализации доступных внешних команд.
Оболочка не обязательно знает cat
, что такое. Потенциально это может быть любая команда из любого места в вашем $PATH
или функция.
Если бы он был встроен -в команду (, что может быть в некоторых оболочках ), он имел бы возможность реорганизовать конвейер, поскольку он знал бы о семантике он построен -в команде cat
. Перед тем, как это сделать, необходимо дополнительно сделать предположения о следующей команде в конвейере после исходной cat
.
Обратите внимание, что чтение из стандартного ввода ведет себя немного по-разному, когда оно подключено к каналу и когда оно подключено к файлу. Канал не доступен для поиска, поэтому в зависимости от того, что делает следующая команда в конвейере,он может вести себя по-разному, а может и не вести себя, если конвейер был перестроен (он может определить, доступны ли входные данные для поиска, и решить, делать ли что-то по-другому, если это так или нет, в любом случае он будет вести себя по-другому ).
Этот вопрос похож (в очень общем смысле )на " Существуют ли какие-либо компиляторы, которые пытаются исправить синтаксические ошибки самостоятельно? " (на сайте Software Engineering StackExchange ), хотя этот вопрос, очевидно, касается синтаксических ошибок, а не бесполезных шаблонов проектирования. Однако идея автоматического изменения кода в зависимости от намерения во многом такая же.
Потому что это не бесполезно.
В случае cat file | cmd
fd0
(stdin )из cmd
будет каналом, а в случае cmd <file
это может быть обычный файл, устройство и т. д.
Конвейер имеет семантику, отличную от семантики обычного файла, и его семантика не является подмножеством семантики обычного файла:
обычный файл нельзя select(2)
редактировать или poll(2)
редактировать осмысленным образом; a select(2)
на нем всегда будет возвращать «готово». Расширенные интерфейсы, такие как epoll(2)
в Linux, просто не будут работать с обычными файлами.
в Linux есть системные вызовы (splice(2)
, vmsplice(2)
, tee(2)
), которые работают только с каналами [1]
Поскольку cat
так часто используется, его можно было бы реализовать как встроенную оболочку -, в которой не будет дополнительного процесса, но как только вы начнете этот путь, то же самое можно будет сделать с большинством команд --. ] превращая оболочку в более медленную и громоздкую perl
или python
. возможно, лучше написать другой язык сценариев с простым в использовании синтаксисом -типа конвейера для продолжений ;-)
[1] Если вам нужен простой пример, не придуманный по случаю, вы можете посмотреть мой "exec binary from stdin" git gist с некоторыми пояснениями в комментарии здесь . Реализация cat
внутри него, чтобы заставить его работать без UUoC, увеличила бы его в 2 или 3 раза.
Добавление к ответу @Kusalananda (и комментарию @alephzero ), кошка может быть чем угодно:
alias cat='gcc -c'
cat "$MYFILE" | command1 | command2 > "$OUTPUT"
или
echo 'echo 1' > /usr/bin/cat
cat "$MYFILE" | command1 | command2 > "$OUTPUT"
Нет никакой причины, по которой cat (сам по себе )или /usr/bin/cat в системе на самом деле является cat средством объединения.
Команда cat
может принимать -
в качестве маркера для stdin .(POSIX , " Если файл ' -', утилита cat должна прочитать стандартный ввод в этой точке последовательности. " )Это позволяет легко обрабатывать файл или стандартный ввод , где в противном случае это было бы запрещено.
Рассмотрим эти две тривиальные альтернативы, где аргумент оболочки $1
равен-
:
cat "$1" | nl # Works completely transparently
nl < "$1" # Fails with 'bash: -: No such file or directory'
Другой случай cat
полезен, когда он преднамеренно используется как операция no -просто для поддержания синтаксиса оболочки:
file="$1"
reader=cat
[[ $file =~ \.gz$ ]] && reader=zcat
[[ $file =~ \.bz2$ ]] && reader=bzcat
"$reader" "$file"
Наконец, я считаю, что единственный случай, когда UUOC действительно может быть правильно вызван, это когда cat
используется с именем файла, которое, как известно, является обычным файлом (, то есть не устройством или именованным каналом ), и что команде не даются флаги:
cat file.txt
В любой другой ситуации могут потребоваться операции самого cat
.
Потому что обнаружить бесполезного кота действительно очень сложно.
У меня был сценарий оболочки, в котором я написал
cat | (somecommand <<!
...
/proc/self/fd/3
...
!) 0<&3
Сценарий оболочки не работал в рабочей среде, если cat
был удален из-за того, что он был вызван через su -c 'script.sh' someuser
. Явно лишний cat
заставил владельца стандартного ввода измениться на пользователя, от имени которого выполнялся скрипт, так что его повторное открытие через /proc
сработало.
tl;dr:Оболочки не делают этого автоматически, потому что затраты превышают вероятные выгоды.
В других ответах указывалось на техническую разницу между stdin, являющимся каналом, и файлом. Имея это в виду, снаряд может выполнить одно из:
cat
как встроенную функцию, сохранив различие между файлом и каналом. Это сэкономит затраты на exec и, возможно, на форк. Затем вы должны рассмотреть затраты и преимущества каждого подхода. Преимущества достаточно просты:
cat
)Таким образом, вы сэкономите немного процессорного времени и памяти, особенно если сможете избежать форка. Конечно, вы экономите это время и память только тогда, когда функция действительно используется. И вы действительно экономите только время fork/exec; с большими файлами время в основном является временем ввода-вывода (, т. е. чтением файла с диска ). Таким образом, вы должны спросить :, как часто cat
используется (бесполезно )в сценариях оболочки, где производительность действительно имеет значение? Сравните его с другими распространенными встроенными командами оболочки, такими как test
— трудно представить, что cat
используется (бесполезно )даже в десять раз реже, чем test
используется в важных местах. Это предположение, которое я не измерял, и это то, что вы хотели бы сделать перед любой попыткой реализации. (Или аналогичным образом попросить кого-то еще реализовать, например, запрос функции.)
Затем вы спрашиваете :, каковы затраты. Две затраты, которые приходят на ум, это ()дополнительный код в оболочке, который увеличивает его размер (и, следовательно, возможно использование памяти ), требует дополнительных работ по обслуживанию, является еще одним местом для ошибок и т. д. ; и (b )обратная совместимость удивляет, POSIX cat
опускает многие функции, например, GNU coreutils cat
, так что вы должны быть осторожны, что именно будет реализовывать встроенный cat
.
Дополнительная встроенная опция, вероятно, не так уж и плоха — добавление еще одной встроенной функции там, где уже существует множество. Если бы у вас были данные профилирования, показывающие, что это поможет, вы, вероятно, могли бы убедить авторов вашей любимой оболочки добавить ее.
Что касается анализа конвейера, я не думаю, что в настоящее время оболочки делают что-то подобное (некоторые распознают конец конвейера и могут избежать разветвления ). По сути, вы добавляете в оболочку (примитивный )оптимизатор; оптимизаторы часто оказываются сложным кодом и источником множества ошибок.И эти ошибки могут быть удивительными — небольшие изменения в сценарии оболочки могут привести к тому, что ошибка будет устранена или спровоцирована.
Постскриптум:Вы можете применить аналогичный анализ к вашему бесполезному использованию кота. Преимущества :легче читать (хотя, если command1 будет принимать файл в качестве аргумента, вероятно, нет ). Стоит :лишнее fork и exec (и если command1 может принимать файл в качестве аргумента, вероятно больше запутанных сообщений об ошибках ). Если ваш анализ говорит вам бесполезно использовать кошку, тогда вперед.
Помимо всего прочего, проверкаcat
-добавит дополнительную нагрузку на производительность и создаст путаницу в отношении того, какое использование cat
на самом деле бесполезно, ИМХО, потому что такие проверки могут быть неэффективными и создавать проблемы с законным cat
использованием.
Когда команды имеют дело со стандартными потоками, они должны заботиться только о чтении/записи в стандартные файловые дескрипторы. Команды могут знать, является ли стандартный ввод доступным для поиска/искания или нет, что указывает на канал или файл.
Если мы добавим к этой смеси проверку того, какой процесс на самом деле предоставляет это содержимое стандартного ввода, нам нужно будет найти процесс на другой стороне конвейера и применить соответствующую оптимизацию. Это можно сделать с точки зрения самой оболочки, как показано в сообщении SuperUser Кайла Джонса, и с точки зрения оболочки
(find /proc -type l | xargs ls -l | fgrep 'pipe:[20043922]') 2>/dev/null
, как показано в связанном посте. Это еще 3 команды (, так что дополнительные fork()
s и exec()
s )и рекурсивные обходы (так много readdir()
вызовов ).
С точки зрения исходного кода C и оболочки, оболочка уже знает дочерний процесс, поэтому нет необходимости в рекурсии, но как мы узнаем, когда оптимизировать, а когда cat
на самом деле бесполезно? На самом деле существуют полезные применения cat , такие как
# adding header and footer to file
( cmd; cat file; cmd ) | cmd
# tr command does not accept files as arguments
cat log1 log2 log3 | tr '[:upper:]' '[:lower:]'
Вероятно, добавление такой оптимизации в оболочку было бы расточительством и ненужными накладными расходами. Как уже упоминалось в ответе Кусаланды, UUOC больше связан с отсутствием у пользователя понимания того, как лучше всего комбинировать команды для достижения наилучших результатов.