How can I suppress error messages for a shell command?
For example, if there are only jpg files in a directory, running ls *.zip gives an error message:
$ ls *.zip
ls: cannot access '*.zip': No such file or directory
Is there an option to suppress such error messages? I want to use this command in a Bash script, but I want to hide all errors.
![]()
asked Sep 3, 2015 at 15:31
![]()
6
Most Unix commands, including ls, will write regular output to standard output and error messages to standard error, so you can use Bash redirection to throw away the error messages while leaving the regular output in place:
ls *.zip 2> /dev/null
![]()
answered Sep 3, 2015 at 15:33
AJefferissAJefferiss
1,5931 gold badge12 silver badges17 bronze badges
1
$ ls *.zip 2>/dev/null
will redirect any error messages on stderr to /dev/null (i.e. you won’t see them)
Note the return value (given by $?) will still reflect that an error occurred.
answered Sep 3, 2015 at 15:34
Brian AgnewBrian Agnew
268k36 gold badges333 silver badges440 bronze badges
To suppress error messages and also return the exit status zero, append || true. For example:
$ ls *.zip && echo hello
ls: cannot access *.zip: No such file or directory
$ ls *.zip 2>/dev/null && echo hello
$ ls *.zip 2>/dev/null || true && echo hello
hello
$ touch x.zip
$ ls *.zip 2>/dev/null || true && echo hello
x.zip
hello
![]()
answered Nov 11, 2017 at 6:45
A-CA-C
1211 silver badge4 bronze badges
2
I attempted ls -R [existing file] and got an immediate error.
ls: cannot access ‘existing file’: No such file or directory
So, I used the following:
ls -R 2>dev/null | grep -i [existing file]*
ls -R 2>dev/null | grep -i text*
Or, in your case:
ls -R 2>dev/null | grep -i *.zip
answered Jan 4, 2022 at 19:36
1
My solution with a raspberry pi3 with buster.
ls -R 2>/dev/null | grep -i [existing file]*
2>/dev/null is very usefull with Bash script to avoid useless warnings or errors.
Do not forget slash caracter
answered Feb 6 at 13:32
![]()
1
8.4.2. Подавление вывода сообщений об ошибках
Допустим, вы хотите найти запись пользователя louise в системном файле паролей:
$ grep louise /etc/passwd
louise:lxAL6GW9G.ZyY:501:501:Accounts Sect1С:/home/accts/louise:/bin/sh
He исключена возможность, что вы забудете, как называется этот файл. В таком случае воспользуйтесь следующей командой:
$ grep louise /etc/password
grep: /etc/password: No such file or directory
Команда grep выводит сообщение об ошибке, в которой говорится о том, что указанного файла не существует. Можно попробовать провести поиск во всех файлах каталога /etc:
$ grep louise /etc/*
Однако в результате будут выведены многочисленные сообщения об ошибках, гласящие, что к определенным файлам доступ запрещен, а некоторые элементы каталога являются подкаталогами и поиск в них не ведется.
В подобной ситуации можно воспользоваться опцией -s, которая подавляет вывод сообщений об ошибках:
$ grep -a louise /etc/*
Если ваша версия команды grep не поддерживает данную опцию, воспользуйтесь следующей командой:
$ grep louise /etc/* 2> /dev/null
Эта команда направляет поток ошибок (2>) в системную корзину (устройство /dev/null). На жаргоне системных администраторов это устройство называется битодробилкой.
Читайте также
Уровни вывода сообщений ядра
Уровни вывода сообщений ядра
Главное отличие между функциями printk() и printf() — это возможность в первой указывать уровень вывода сообщений ядра (loglevel). Ядро использует уровень вывода сообщений для принятия решения о том, выводить сообщение на консоль или нет. Ядро выводит на
Отправка сообщений об ошибках
Отправка сообщений об ошибках
Если вы обнаружили ошибку, то наилучшим решением будет исправить ее, сгенерировать соответствующую заплату, оттестировать и отправить, как это будет рассказано в следующих разделах. Конечно, можно и просто сообщить об ошибке, чтобы
7.2 Сообщения об ошибках ICMP
7.2 Сообщения об ошибках ICMP
Бывают ситуации, приводящие к отбрасыванию (удалению из сети) датаграммы IP. Например, точка назначения может стать недоступной из-за обрыва связи. Или может завершиться время жизни датаграммы. Маршрутизатор не сможет переслать длинную
7.2.1 Типы сообщений об ошибках
7.2.1 Типы сообщений об ошибках
На рис. 7.3 показаны обобщенные сообщения, формируемые маршрутизатором и хостом назначения для отчета о возникшей проблеме. В таблице 7.1 перечислены формальные имена сообщений об ошибках ICMP.
Рис. 7.3. Типы сообщений об ошибках ICMPТаблица 7.1
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
В.З. Стандартные функции вывода сообщений об ошибках
В.З. Стандартные функции вывода сообщений об ошибках
Мы определили свой набор функций, используемых во всех программах книги для обработки ситуаций с возникновением ошибок. Причина, по которой мы создаем эти функции, заключается в том, что теперь мы можем писать команды в
Отчет об ошибках
Отчет об ошибках
На вкладке Дополнительно в окне Свойства системы нажимаем кнопку Отчет об ошибках. Откроется одноименное окно Отчет об ошибках (рис. 4.5), в котором устанавливаем переключатель в положение Отключить отчет об ошибках и оставляем установленным флажок Но
Получение и пересылка сообщений. Создание ответных сообщений
Получение и пересылка сообщений. Создание ответных сообщений
Чтобы получить новую почту, выполните команду главного меню Сервис ? Отправить/Получить ? Доставить почту либо нажмите клавишу F9. Все полученные почтовые сообщения будут помещены в папку Входящие и помечены
Шаг 20 — Временные объекты. Неявные вызовы конструкторов и их подавление.
Шаг 20 — Временные объекты. Неявные вызовы конструкторов и их подавление.
Не удается углубиться в какую-либо тему. Приходится касаться по верхам, потом переключаться на что-то другое. С другой стороны, может это и правильно, часто достаточно только знать, что есть ТАКОЕ
Настройка вывода сообщений об ошибках с помощью ‹customErrors›
Настройка вывода сообщений об ошибках с помощью ‹customErrors›
Элемент ‹customErrors› может использоваться для автоматического перенаправления всех ошибок в пользовательский набор файлов *.htm. Это может оказаться полезным тогда, когда вы хотите построить более понятную для
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
Сообщение об ошибках gbak
Сообщение об ошибках gbak
В табл. 38.3 описаны сообщения об ошибках, которые могут возникнуть в процессе копирования и восстановления, вместе с некоторыми советами, как поступать с этими ошибками.Таблица 38.3. Сообщения об ошибках gbak при копировании и восстановлении
Сообщение
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий . Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
Отчеты об ошибках
Отчеты об ошибках
В операционной системе Windows Vista реализован новый механизм отчетов об ошибках. Теперь ограничить и настроить его работу можно с помощью следующих параметров, расположенных в ветви реестра HKEY_CURRENT_USERSoftwarePoliciesMicrosoftWindowsWindows Error Reporting. Если не сказано иное,
How can I suppress error messages for a shell command?
For example, if there are only jpg files in a directory, running ls *.zip gives an error message:
$ ls *.zip
ls: cannot access '*.zip': No such file or directory
Is there an option to suppress such error messages? I want to use this command in a Bash script, but I want to hide all errors.
![]()
asked Sep 3, 2015 at 15:31
![]()
6
Most Unix commands, including ls, will write regular output to standard output and error messages to standard error, so you can use Bash redirection to throw away the error messages while leaving the regular output in place:
ls *.zip 2> /dev/null
![]()
answered Sep 3, 2015 at 15:33
AJefferissAJefferiss
1,5931 gold badge12 silver badges17 bronze badges
1
$ ls *.zip 2>/dev/null
will redirect any error messages on stderr to /dev/null (i.e. you won’t see them)
Note the return value (given by $?) will still reflect that an error occurred.
answered Sep 3, 2015 at 15:34
Brian AgnewBrian Agnew
268k36 gold badges333 silver badges440 bronze badges
To suppress error messages and also return the exit status zero, append || true. For example:
$ ls *.zip && echo hello
ls: cannot access *.zip: No such file or directory
$ ls *.zip 2>/dev/null && echo hello
$ ls *.zip 2>/dev/null || true && echo hello
hello
$ touch x.zip
$ ls *.zip 2>/dev/null || true && echo hello
x.zip
hello
![]()
answered Nov 11, 2017 at 6:45
A-CA-C
1211 silver badge4 bronze badges
2
I attempted ls -R [existing file] and got an immediate error.
ls: cannot access ‘existing file’: No such file or directory
So, I used the following:
ls -R 2>dev/null | grep -i [existing file]*
ls -R 2>dev/null | grep -i text*
Or, in your case:
ls -R 2>dev/null | grep -i *.zip
answered Jan 4, 2022 at 19:36
1
My solution with a raspberry pi3 with buster.
ls -R 2>/dev/null | grep -i [existing file]*
2>/dev/null is very usefull with Bash script to avoid useless warnings or errors.
Do not forget slash caracter
answered Feb 6 at 13:32
![]()
1
8.4.2. Подавление вывода сообщений об ошибках
Допустим, вы хотите найти запись пользователя louise в системном файле паролей:
$ grep louise /etc/passwd
louise:lxAL6GW9G.ZyY:501:501:Accounts Sect1С:/home/accts/louise:/bin/sh
He исключена возможность, что вы забудете, как называется этот файл. В таком случае воспользуйтесь следующей командой:
$ grep louise /etc/password
grep: /etc/password: No such file or directory
Команда grep выводит сообщение об ошибке, в которой говорится о том, что указанного файла не существует. Можно попробовать провести поиск во всех файлах каталога /etc:
$ grep louise /etc/*
Однако в результате будут выведены многочисленные сообщения об ошибках, гласящие, что к определенным файлам доступ запрещен, а некоторые элементы каталога являются подкаталогами и поиск в них не ведется.
В подобной ситуации можно воспользоваться опцией -s, которая подавляет вывод сообщений об ошибках:
$ grep -a louise /etc/*
Если ваша версия команды grep не поддерживает данную опцию, воспользуйтесь следующей командой:
$ grep louise /etc/* 2> /dev/null
Эта команда направляет поток ошибок (2>) в системную корзину (устройство /dev/null). На жаргоне системных администраторов это устройство называется битодробилкой.
Читайте также
Уровни вывода сообщений ядра
Уровни вывода сообщений ядра
Главное отличие между функциями printk() и printf() — это возможность в первой указывать уровень вывода сообщений ядра (loglevel). Ядро использует уровень вывода сообщений для принятия решения о том, выводить сообщение на консоль или нет. Ядро выводит на
Отправка сообщений об ошибках
Отправка сообщений об ошибках
Если вы обнаружили ошибку, то наилучшим решением будет исправить ее, сгенерировать соответствующую заплату, оттестировать и отправить, как это будет рассказано в следующих разделах. Конечно, можно и просто сообщить об ошибке, чтобы
7.2 Сообщения об ошибках ICMP
7.2 Сообщения об ошибках ICMP
Бывают ситуации, приводящие к отбрасыванию (удалению из сети) датаграммы IP. Например, точка назначения может стать недоступной из-за обрыва связи. Или может завершиться время жизни датаграммы. Маршрутизатор не сможет переслать длинную
7.2.1 Типы сообщений об ошибках
7.2.1 Типы сообщений об ошибках
На рис. 7.3 показаны обобщенные сообщения, формируемые маршрутизатором и хостом назначения для отчета о возникшей проблеме. В таблице 7.1 перечислены формальные имена сообщений об ошибках ICMP.
Рис. 7.3. Типы сообщений об ошибках ICMPТаблица 7.1
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
В.З. Стандартные функции вывода сообщений об ошибках
В.З. Стандартные функции вывода сообщений об ошибках
Мы определили свой набор функций, используемых во всех программах книги для обработки ситуаций с возникновением ошибок. Причина, по которой мы создаем эти функции, заключается в том, что теперь мы можем писать команды в
Отчет об ошибках
Отчет об ошибках
На вкладке Дополнительно в окне Свойства системы нажимаем кнопку Отчет об ошибках. Откроется одноименное окно Отчет об ошибках (рис. 4.5), в котором устанавливаем переключатель в положение Отключить отчет об ошибках и оставляем установленным флажок Но
Получение и пересылка сообщений. Создание ответных сообщений
Получение и пересылка сообщений. Создание ответных сообщений
Чтобы получить новую почту, выполните команду главного меню Сервис ? Отправить/Получить ? Доставить почту либо нажмите клавишу F9. Все полученные почтовые сообщения будут помещены в папку Входящие и помечены
Шаг 20 — Временные объекты. Неявные вызовы конструкторов и их подавление.
Шаг 20 — Временные объекты. Неявные вызовы конструкторов и их подавление.
Не удается углубиться в какую-либо тему. Приходится касаться по верхам, потом переключаться на что-то другое. С другой стороны, может это и правильно, часто достаточно только знать, что есть ТАКОЕ
Настройка вывода сообщений об ошибках с помощью ‹customErrors›
Настройка вывода сообщений об ошибках с помощью ‹customErrors›
Элемент ‹customErrors› может использоваться для автоматического перенаправления всех ошибок в пользовательский набор файлов *.htm. Это может оказаться полезным тогда, когда вы хотите построить более понятную для
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
Сообщение об ошибках gbak
Сообщение об ошибках gbak
В табл. 38.3 описаны сообщения об ошибках, которые могут возникнуть в процессе копирования и восстановления, вместе с некоторыми советами, как поступать с этими ошибками.Таблица 38.3. Сообщения об ошибках gbak при копировании и восстановлении
Сообщение
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий . Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
Подавление линий заднего плана
Подавление линий заднего плана
Команда HIDE обеспечивает создание рисунка без скрытых линий. Сложные трехмерные модели часто оказываются перегруженными, что затрудняет их чтение и просмотр результатов выполнения какой-либо команды на объекте. Можно устранить эту
Отчеты об ошибках
Отчеты об ошибках
В операционной системе Windows Vista реализован новый механизм отчетов об ошибках. Теперь ограничить и настроить его работу можно с помощью следующих параметров, расположенных в ветви реестра HKEY_CURRENT_USERSoftwarePoliciesMicrosoftWindowsWindows Error Reporting. Если не сказано иное,
How can I suppress error messages for a shell command?
For example, if there are only jpg files in a directory, running ls *.zip gives an error message:
$ ls *.zip
ls: cannot access '*.zip': No such file or directory
Is there an option to suppress such error messages? I want to use this command in a Bash script, but I want to hide all errors.
![]()
asked Sep 3, 2015 at 15:31
![]()
6
Most Unix commands, including ls, will write regular output to standard output and error messages to standard error, so you can use Bash redirection to throw away the error messages while leaving the regular output in place:
ls *.zip 2> /dev/null
![]()
answered Sep 3, 2015 at 15:33
AJefferissAJefferiss
1,5631 gold badge12 silver badges17 bronze badges
1
$ ls *.zip 2>/dev/null
will redirect any error messages on stderr to /dev/null (i.e. you won’t see them)
Note the return value (given by $?) will still reflect that an error occurred.
answered Sep 3, 2015 at 15:34
Brian AgnewBrian Agnew
266k36 gold badges331 silver badges438 bronze badges
To suppress error messages and also return the exit status zero, append || true. For example:
$ ls *.zip && echo hello
ls: cannot access *.zip: No such file or directory
$ ls *.zip 2>/dev/null && echo hello
$ ls *.zip 2>/dev/null || true && echo hello
hello
$ touch x.zip
$ ls *.zip 2>/dev/null || true && echo hello
x.zip
hello
![]()
answered Nov 11, 2017 at 6:45
A-CA-C
1211 silver badge4 bronze badges
2
I attempted ls -R [existing file] and got an immediate error.
ls: cannot access ‘existing file’: No such file or directory
So, I used the following:
ls -R 2>dev/null | grep -i [existing file]*
ls -R 2>dev/null | grep -i text*
Or, in your case:
ls -R 2>dev/null | grep -i *.zip
answered Jan 4, 2022 at 19:36
1
Note:
- This answer probably goes deeper than the use case warrants, and
find 2>/dev/nullmay be good enough in many situations. It may still be of interest for a cross-platform perspective and for its discussion of some advanced shell techniques in the interest of finding a solution that is as robust as possible, even though the cases guarded against may be largely hypothetical.
If your shell is bash or zsh, there’s a solution that is robust while being reasonably simple, using only POSIX-compliant find features; while bash itself is not part of POSIX, most modern Unix platforms come with it, making this solution widely portable:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Note:
-
If your system is configured to show localized error messages, prefix the
findcalls below withLC_ALL=C(LC_ALL=C find ...) to ensure that English messages are reported, so thatgrep -v 'Permission denied'works as intended. Invariably, however, any error messages that do get displayed will then be in English as well. -
>(...)is a (rarely used) output process substitution that allows redirecting output (in this case, stderr output (2>) to the stdin of the command inside>(...).
In addition tobashandzsh,kshsupports them as well in principle, but trying to combine them with redirection from stderr, as is done here (2> >(...)), appears to be silently ignored (inksh 93u+).-
grep -v 'Permission denied'filters out (-v) all lines (from thefindcommand’s stderr stream) that contain the phrasePermission deniedand outputs the remaining lines to stderr (>&2). -
Note: There’s a small chance that some of
grep‘s output may arrive afterfindcompletes, because the overall command doesn’t wait for the command inside>(...)to finish. Inbash, you can prevent this by appending| catto the command.
-
This approach is:
-
robust:
grepis only applied to error messages (and not to a combination of file paths and error messages, potentially leading to false positives), and error messages other than permission-denied ones are passed through, to stderr. -
side-effect free:
find‘s exit code is preserved: the inability to access at least one of the filesystem items encountered results in exit code1(although that won’t tell you whether errors other than permission-denied ones occurred (too)).
POSIX-compliant solutions:
Fully POSIX-compliant solutions either have limitations or require additional work.
If find‘s output is to be captured in a file anyway (or suppressed altogether), then the pipeline-based solution from Jonathan Leffler’s answer is simple, robust, and POSIX-compliant:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Note that the order of the redirections matters: 2>&1 must come first.
Capturing stdout output in a file up front allows 2>&1 to send only error messages through the pipeline, which grep can then unambiguously operate on.
The only downside is that the overall exit code will be the grep command’s, not find‘s, which in this case means: if there are no errors at all or only permission-denied errors, the exit code will be 1 (signaling failure), otherwise (errors other than permission-denied ones) 0 — which is the opposite of the intent.
That said, find‘s exit code is rarely used anyway, as it often conveys little information beyond fundamental failure such as passing a non-existent path.
However, the specific case of even only some of the input paths being inaccessible due to lack of permissions is reflected in find‘s exit code (in both GNU and BSD find): if a permissions-denied error occurs for any of the files processed, the exit code is set to 1.
The following variation addresses that:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Now, the exit code indicates whether any errors other than Permission denied occurred: 1 if so, 0 otherwise.
In other words: the exit code now reflects the true intent of the command: success (0) is reported, if no errors at all or only permission-denied errors occurred.
This is arguably even better than just passing find‘s exit code through, as in the solution at the top.
gniourf_gniourf in the comments proposes a (still POSIX-compliant) generalization of this solution using sophisticated redirections, which works even with the default behavior of printing the file paths to stdout:
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
In short: Custom file descriptor 3 is used to temporarily swap stdout (1) and stderr (2), so that error messages alone can be piped to grep via stdout.
Without these redirections, both data (file paths) and error messages would be piped to grep via stdout, and grep would then not be able to distinguish between error message Permission denied and a (hypothetical) file whose name happens to contain the phrase Permission denied.
As in the first solution, however, the the exit code reported will be grep‘s, not find‘s, but the same fix as above can be applied.
Notes on the existing answers:
-
There are several points to note about Michael Brux’s answer,
find . ! -readable -prune -o -print:-
It requires GNU
find; notably, it won’t work on macOS. Of course, if you only ever need the command to work with GNUfind, this won’t be a problem for you. -
Some
Permission deniederrors may still surface:find ! -readable -prunereports such errors for the child items of directories for which the current user does haverpermission, but lacksx(executable) permission. The reason is that because the directory itself is readable,-pruneis not executed, and the attempt to descend into that directory then triggers the error messages. That said, the typical case is for therpermission to be missing. -
Note: The following point is a matter of philosophy and/or specific use case, and you may decide it is not relevant to you and that the command fits your needs well, especially if simply printing the paths is all you do:
- If you conceptualize the filtering of the permission-denied error messages a separate task that you want to be able to apply to any
findcommand, then the opposite approach of proactively preventing permission-denied errors requires introducing «noise» into thefindcommand, which also introduces complexity and logical pitfalls. - For instance, the most up-voted comment on Michael’s answer (as of this writing) attempts to show how to extend the command by including a
-namefilter, as follows:
find . ! -readable -prune -o -name '*.txt'
This, however, does not work as intended, because the trailing-printaction is required (an explanation can be found in this answer). Such subtleties can introduce bugs.
- If you conceptualize the filtering of the permission-denied error messages a separate task that you want to be able to apply to any
-
-
The first solution in Jonathan Leffler’s answer,
find . 2>/dev/null > files_and_folders, as he himself states, blindly silences all error messages (and the workaround is cumbersome and not fully robust, as he also explains). Pragmatically speaking, however, it is the simplest solution, as you may be content to assume that any and all errors would be permission-related. -
mist’s answer,
sudo find . > files_and_folders, is concise and pragmatic, but ill-advised for anything other than merely printing filenames, for security reasons: because you’re running as the root user, «you risk having your whole system being messed up by a bug in find or a malicious version, or an incorrect invocation which writes something unexpectedly, which could not happen if you ran this with normal privileges» (from a comment on mist’s answer by tripleee). -
The 2nd solution in viraptor’s answer,
find . 2>&1 | grep -v 'Permission denied' > some_fileruns the risk of false positives (due to sending a mix of stdout and stderr through the pipeline), and, potentially, instead of reporting non-permission-denied errors via stderr, captures them alongside the output paths in the output file.
Note:
- This answer probably goes deeper than the use case warrants, and
find 2>/dev/nullmay be good enough in many situations. It may still be of interest for a cross-platform perspective and for its discussion of some advanced shell techniques in the interest of finding a solution that is as robust as possible, even though the cases guarded against may be largely hypothetical.
If your shell is bash or zsh, there’s a solution that is robust while being reasonably simple, using only POSIX-compliant find features; while bash itself is not part of POSIX, most modern Unix platforms come with it, making this solution widely portable:
find . > files_and_folders 2> >(grep -v 'Permission denied' >&2)
Note:
-
If your system is configured to show localized error messages, prefix the
findcalls below withLC_ALL=C(LC_ALL=C find ...) to ensure that English messages are reported, so thatgrep -v 'Permission denied'works as intended. Invariably, however, any error messages that do get displayed will then be in English as well. -
>(...)is a (rarely used) output process substitution that allows redirecting output (in this case, stderr output (2>) to the stdin of the command inside>(...).
In addition tobashandzsh,kshsupports them as well in principle, but trying to combine them with redirection from stderr, as is done here (2> >(...)), appears to be silently ignored (inksh 93u+).-
grep -v 'Permission denied'filters out (-v) all lines (from thefindcommand’s stderr stream) that contain the phrasePermission deniedand outputs the remaining lines to stderr (>&2). -
Note: There’s a small chance that some of
grep‘s output may arrive afterfindcompletes, because the overall command doesn’t wait for the command inside>(...)to finish. Inbash, you can prevent this by appending| catto the command.
-
This approach is:
-
robust:
grepis only applied to error messages (and not to a combination of file paths and error messages, potentially leading to false positives), and error messages other than permission-denied ones are passed through, to stderr. -
side-effect free:
find‘s exit code is preserved: the inability to access at least one of the filesystem items encountered results in exit code1(although that won’t tell you whether errors other than permission-denied ones occurred (too)).
POSIX-compliant solutions:
Fully POSIX-compliant solutions either have limitations or require additional work.
If find‘s output is to be captured in a file anyway (or suppressed altogether), then the pipeline-based solution from Jonathan Leffler’s answer is simple, robust, and POSIX-compliant:
find . 2>&1 >files_and_folders | grep -v 'Permission denied' >&2
Note that the order of the redirections matters: 2>&1 must come first.
Capturing stdout output in a file up front allows 2>&1 to send only error messages through the pipeline, which grep can then unambiguously operate on.
The only downside is that the overall exit code will be the grep command’s, not find‘s, which in this case means: if there are no errors at all or only permission-denied errors, the exit code will be 1 (signaling failure), otherwise (errors other than permission-denied ones) 0 — which is the opposite of the intent.
That said, find‘s exit code is rarely used anyway, as it often conveys little information beyond fundamental failure such as passing a non-existent path.
However, the specific case of even only some of the input paths being inaccessible due to lack of permissions is reflected in find‘s exit code (in both GNU and BSD find): if a permissions-denied error occurs for any of the files processed, the exit code is set to 1.
The following variation addresses that:
find . 2>&1 >files_and_folders | { grep -v 'Permission denied' >&2; [ $? -eq 1 ]; }
Now, the exit code indicates whether any errors other than Permission denied occurred: 1 if so, 0 otherwise.
In other words: the exit code now reflects the true intent of the command: success (0) is reported, if no errors at all or only permission-denied errors occurred.
This is arguably even better than just passing find‘s exit code through, as in the solution at the top.
gniourf_gniourf in the comments proposes a (still POSIX-compliant) generalization of this solution using sophisticated redirections, which works even with the default behavior of printing the file paths to stdout:
{ find . 3>&2 2>&1 1>&3 | grep -v 'Permission denied' >&3; } 3>&2 2>&1
In short: Custom file descriptor 3 is used to temporarily swap stdout (1) and stderr (2), so that error messages alone can be piped to grep via stdout.
Without these redirections, both data (file paths) and error messages would be piped to grep via stdout, and grep would then not be able to distinguish between error message Permission denied and a (hypothetical) file whose name happens to contain the phrase Permission denied.
As in the first solution, however, the the exit code reported will be grep‘s, not find‘s, but the same fix as above can be applied.
Notes on the existing answers:
-
There are several points to note about Michael Brux’s answer,
find . ! -readable -prune -o -print:-
It requires GNU
find; notably, it won’t work on macOS. Of course, if you only ever need the command to work with GNUfind, this won’t be a problem for you. -
Some
Permission deniederrors may still surface:find ! -readable -prunereports such errors for the child items of directories for which the current user does haverpermission, but lacksx(executable) permission. The reason is that because the directory itself is readable,-pruneis not executed, and the attempt to descend into that directory then triggers the error messages. That said, the typical case is for therpermission to be missing. -
Note: The following point is a matter of philosophy and/or specific use case, and you may decide it is not relevant to you and that the command fits your needs well, especially if simply printing the paths is all you do:
- If you conceptualize the filtering of the permission-denied error messages a separate task that you want to be able to apply to any
findcommand, then the opposite approach of proactively preventing permission-denied errors requires introducing «noise» into thefindcommand, which also introduces complexity and logical pitfalls. - For instance, the most up-voted comment on Michael’s answer (as of this writing) attempts to show how to extend the command by including a
-namefilter, as follows:
find . ! -readable -prune -o -name '*.txt'
This, however, does not work as intended, because the trailing-printaction is required (an explanation can be found in this answer). Such subtleties can introduce bugs.
- If you conceptualize the filtering of the permission-denied error messages a separate task that you want to be able to apply to any
-
-
The first solution in Jonathan Leffler’s answer,
find . 2>/dev/null > files_and_folders, as he himself states, blindly silences all error messages (and the workaround is cumbersome and not fully robust, as he also explains). Pragmatically speaking, however, it is the simplest solution, as you may be content to assume that any and all errors would be permission-related. -
mist’s answer,
sudo find . > files_and_folders, is concise and pragmatic, but ill-advised for anything other than merely printing filenames, for security reasons: because you’re running as the root user, «you risk having your whole system being messed up by a bug in find or a malicious version, or an incorrect invocation which writes something unexpectedly, which could not happen if you ran this with normal privileges» (from a comment on mist’s answer by tripleee). -
The 2nd solution in viraptor’s answer,
find . 2>&1 | grep -v 'Permission denied' > some_fileruns the risk of false positives (due to sending a mix of stdout and stderr through the pipeline), and, potentially, instead of reporting non-permission-denied errors via stderr, captures them alongside the output paths in the output file.
Bash-скрипты: начало
Bash-скрипты, часть 2: циклы
Bash-скрипты, часть 3: параметры и ключи командной строки
Bash-скрипты, часть 4: ввод и вывод
Bash-скрипты, часть 5: сигналы, фоновые задачи, управление сценариями
Bash-скрипты, часть 6: функции и разработка библиотек
Bash-скрипты, часть 7: sed и обработка текстов
Bash-скрипты, часть 8: язык обработки данных awk
Bash-скрипты, часть 9: регулярные выражения
Bash-скрипты, часть 10: практические примеры
Bash-скрипты, часть 11: expect и автоматизация интерактивных утилит
В прошлый раз, в третьей части этой серии материалов по bash-скриптам, мы говорили о параметрах командной строки и ключах. Наша сегодняшняя тема — ввод, вывод, и всё, что с этим связано.


Вы уже знакомы с двумя методами работы с тем, что выводят сценарии командной строки:
- Отображение выводимых данных на экране.
- Перенаправление вывода в файл.
Иногда что-то надо показать на экране, а что-то — записать в файл, поэтому нужно разобраться с тем, как в Linux обрабатывается ввод и вывод, а значит — научиться отправлять результаты работы сценариев туда, куда нужно. Начнём с разговора о стандартных дескрипторах файлов.
Стандартные дескрипторы файлов
Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов.
Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.
0,STDIN —стандартный поток ввода.1,STDOUT —стандартный поток вывода.2,STDERR —стандартный поток ошибок.
Эти три специальных дескриптора обрабатывают ввод и вывод данных в сценарии.
Вам нужно как следует разобраться в стандартных потоках. Их можно сравнить с фундаментом, на котором строится взаимодействие скриптов с внешним миром. Рассмотрим подробности о них.
STDIN
STDIN — это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда в сценариях используют символ перенаправления ввода — <, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.
Многие команды bash принимают ввод из STDIN, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat.
Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN. После того, как вы вводите очередную строку, cat просто выводит её на экран.
STDOUT
STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT, что приводит к их появлению в консоли. Данные можно перенаправить в файл, присоединяя их к его содержимому, для этого служит команда >>.
Итак, у нас есть некий файл с данными, к которому мы можем добавить другие данные с помощью этой команды:
pwd >> myfile
То, что выведет pwd, будет добавлено к файлу myfile, при этом уже имеющиеся в нём данные никуда не денутся.
Перенаправление вывода команды в файл
Пока всё хорошо, но что если попытаться выполнить что-то вроде показанного ниже, обратившись к несуществующему файлу xfile, задумывая всё это для того, чтобы в файл myfile попало сообщение об ошибке.
ls –l xfile > myfile
После выполнения этой команды мы увидим сообщения об ошибках на экране.
Попытка обращения к несуществующему файлу
При попытке обращения к несуществующему файлу генерируется ошибка, но оболочка не перенаправила сообщения об ошибках в файл, выведя их на экран. Но мы-то хотели, чтобы сообщения об ошибках попали в файл. Что делать? Ответ прост — воспользоваться третьим стандартным дескриптором.
STDERR
STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT, именно поэтому при возникновении ошибки мы видим сообщение на экране.
Итак, предположим, что надо перенаправить сообщения об ошибках, скажем, в лог-файл, или куда-нибудь ещё, вместо того, чтобы выводить их на экран.
▍Перенаправление потока ошибок
Как вы уже знаете, дескриптор файла STDERR — 2. Мы можем перенаправить ошибки, разместив этот дескриптор перед командой перенаправления:
ls -l xfile 2>myfile
cat ./myfile
Сообщение об ошибке теперь попадёт в файл myfile.
Перенаправление сообщения об ошибке в файл
▍Перенаправление потоков ошибок и вывода
При написании сценариев командной строки может возникнуть ситуация, когда нужно организовать и перенаправление сообщений об ошибках, и перенаправление стандартного вывода. Для того, чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:
ls –l myfile xfile anotherfile 2> errorcontent 1> correctcontent
Перенаправление ошибок и стандартного вывода
Оболочка перенаправит то, что команда ls обычно отправляет в STDOUT, в файл correctcontent благодаря конструкции 1>. Сообщения об ошибках, которые попали бы в STDERR, оказываются в файле errorcontent из-за команды перенаправления 2>.
Если надо, и STDERR, и STDOUT можно перенаправить в один и тот же файл, воспользовавшись командой &>:
Перенаправление STDERR и STDOUT в один и тот же файл
После выполнения команды то, что предназначено для STDERR и STDOUT, оказывается в файле content.
Перенаправление вывода в скриптах
Существует два метода перенаправления вывода в сценариях командной строки:
- Временное перенаправление, или перенаправление вывода одной строки.
- Постоянное перенаправление, или перенаправление всего вывода в скрипте либо в какой-то его части.
▍Временное перенаправление вывода
В скрипте можно перенаправить вывод отдельной строки в STDERR. Для того, чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR, при этом перед номером дескриптора надо поставить символ амперсанда (&):
#!/bin/bash
echo "This is an error" >&2
echo "This is normal output"
Если запустить скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.
Временное перенаправление
Запустим скрипт так, чтобы вывод STDERR попадал в файл.
./myscript 2> myfile
Как видно, теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл.
Сообщения об ошибках записываются в файл
▍Постоянное перенаправление вывода
Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять соответствующую команду к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec:
#!/bin/bash
exec 1>outfile
echo "This is a test of redirecting all output"
echo "from a shell script to another file."
echo "without having to redirect every line"
Запустим скрипт.
Перенаправление всего вывода в файл
Если просмотреть файл, указанный в команде перенаправления вывода, окажется, что всё, что выводилось командами echo, попало в этот файл.
Команду exec можно использовать не только в начале скрипта, но и в других местах:
#!/bin/bash
exec 2>myerror
echo "This is the start of the script"
echo "now redirecting all output to another location"
exec 1>myfile
echo "This should go to the myfile file"
echo "and this should go to the myerror file" >&2
Вот что получится после запуска скрипта и просмотра файлов, в которые мы перенаправляли вывод.
Перенаправление вывода в разные файлы
Сначала команда exec задаёт перенаправление вывода из STDERR в файл myerror. Затем вывод нескольких команд echo отправляется в STDOUT и выводится на экран. После этого команда exec задаёт отправку того, что попадает в STDOUT, в файл myfile, и, наконец, мы пользуемся командой перенаправления в STDERR в команде echo, что приводит к записи соответствующей строки в файл myerror.
Освоив это, вы сможете перенаправлять вывод туда, куда нужно. Теперь поговорим о перенаправлении ввода.
Перенаправление ввода в скриптах
Для перенаправления ввода можно воспользоваться той же методикой, которую мы применяли для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:
exec 0< myfile
Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл myfile, а не обычный STDIN. Посмотрим на перенаправление ввода в действии:
#!/bin/bash
exec 0< testfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
Вот что появится на экране после запуска скрипта.
Перенаправление ввода
В одном из предыдущих материалов вы узнали о том, как использовать команду read для чтения данных, вводимых пользователем с клавиатуры. Если перенаправить ввод, сделав источником данных файл, то команда read, при попытке прочитать данные из STDIN, будет читать их из файла, а не с клавиатуры.
Некоторые администраторы Linux используют этот подход для чтения и последующей обработки лог-файлов.
Создание собственного перенаправления вывода
Перенаправляя ввод и вывод в сценариях, вы не ограничены тремя стандартными дескрипторами файлов. Как уже говорилось, можно иметь до девяти открытых дескрипторов. Остальные шесть, с номерами от 3 до 8, можно использовать для перенаправления ввода или вывода. Любой из них можно назначить файлу и использовать в коде скрипта.
Назначить дескриптор для вывода данных можно, используя команду exec:
#!/bin/bash
exec 3>myfile
echo "This should display on the screen"
echo "and this should be stored in the file" >&3
echo "And this should be back on the screen"
После запуска скрипта часть вывода попадёт на экран, часть — в файл с дескриптором 3.
Перенаправление вывода, используя собственный дескриптор
Создание дескрипторов файлов для ввода данных
Перенаправить ввод в скрипте можно точно так же, как и вывод. Сохраните STDIN в другом дескрипторе, прежде чем перенаправлять ввод данных.
После окончания чтения файла можно восстановить STDIN и пользоваться им как обычно:
#!/bin/bash
exec 6<&0
exec 0< myfile
count=1
while read line
do
echo "Line #$count: $line"
count=$(( $count + 1 ))
done
exec 0<&6
read -p "Are you done now? " answer
case $answer in
y) echo "Goodbye";;
n) echo "Sorry, this is the end.";;
esac
Испытаем сценарий.
Перенаправление ввода
В этом примере дескриптор файла 6 использовался для хранения ссылки на STDIN. Затем было сделано перенаправление ввода, источником данных для STDIN стал файл. После этого входные данные для команды read поступали из перенаправленного STDIN, то есть из файла.
После чтения файла мы возвращаем STDIN в исходное состояние, перенаправляя его в дескриптор 6. Теперь, для того, чтобы проверить, что всё работает правильно, скрипт задаёт пользователю вопрос, ожидает ввода с клавиатуры и обрабатывает то, что введено.
Закрытие дескрипторов файлов
Оболочка автоматически закрывает дескрипторы файлов после завершения работы скрипта. Однако, в некоторых случаях нужно закрывать дескрипторы вручную, до того, как скрипт закончит работу. Для того, чтобы закрыть дескриптор, его нужно перенаправить в &-. Выглядит это так:
#!/bin/bash
exec 3> myfile
echo "This is a test line of data" >&3
exec 3>&-
echo "This won't work" >&3
После исполнения скрипта мы получим сообщение об ошибке.
Попытка обращения к закрытому дескриптору файла
Всё дело в том, что мы попытались обратиться к несуществующему дескриптору.
Будьте внимательны, закрывая дескрипторы файлов в сценариях. Если вы отправляли данные в файл, потом закрыли дескриптор, потом — открыли снова, оболочка заменит существующий файл новым. То есть всё то, что было записано в этот файл ранее, будет утеряно.
Получение сведений об открытых дескрипторах
Для того, чтобы получить список всех открытых в Linux дескрипторов, можно воспользоваться командой lsof. Во многих дистрибутивах, вроде Fedora, утилита lsof находится в /usr/sbin. Эта команда весьма полезна, так как она выводит сведения о каждом дескрипторе, открытом в системе. Сюда входит и то, что открыли процессы, выполняемые в фоне, и то, что открыто пользователями, вошедшими в систему.
У этой команды есть множество ключей, рассмотрим самые важные.
-pПозволяет указатьIDпроцесса.-dПозволяет указать номер дескриптора, о котором надо получить сведения.
Для того, чтобы узнать PID текущего процесса, можно использовать специальную переменную окружения $$, в которую оболочка записывает текущий PID.
Ключ -a используется для выполнения операции логического И над результатами, возвращёнными благодаря использованию двух других ключей:
lsof -a -p $$ -d 0,1,2
Вывод сведений об открытых дескрипторах
Тип файлов, связанных с STDIN, STDOUT и STDERR — CHR (character mode, символьный режим). Так как все они указывают на терминал, имя файла соответствует имени устройства, назначенного терминалу. Все три стандартных файла доступны и для чтения, и для записи.
Посмотрим на вызов команды lsof из скрипта, в котором открыты, в дополнение к стандартным, другие дескрипторы:
#!/bin/bash
exec 3> myfile1
exec 6> myfile2
exec 7< myfile3
lsof -a -p $$ -d 0,1,2,3,6,7
Вот что получится, если этот скрипт запустить.
Просмотр дескрипторов файлов, открытых скриптом
Скрипт открыл два дескриптора для вывода (3 и 6) и один — для ввода (7). Тут же показаны и пути к файлам, использованных для настройки дескрипторов.
Подавление вывода
Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null. Это — что-то вроде «чёрной дыры».
Вот, например, как подавить вывод сообщений об ошибках:
ls -al badfile anotherfile 2> /dev/null
Тот же подход используется, если, например, надо очистить файл, не удаляя его:
cat /dev/null > myfile
Итоги
Сегодня вы узнали о том, как в сценариях командной строки работают ввод и вывод. Теперь вы умеете обращаться с дескрипторами файлов, создавать, просматривать и закрывать их, знаете о перенаправлении потоков ввода, вывода и ошибок. Всё это очень важно в деле разработки bash-скриптов.
В следующий раз поговорим о сигналах Linux, о том, как обрабатывать их в сценариях, о запуске заданий по расписанию и о фоновых задачах.
Уважаемые читатели! В этом материале даны основы работы с потоками ввода, вывода и ошибок. Уверены, среди вас есть профессионалы, которые могут рассказать обо всём этом то, что приходит лишь с опытом. Если так — передаём слово вам.

Содержание
- Перенаправление ввода/вывода в Linux
- Введение
- Требования
- Потоки
- Стандартный ввод
- Пример
- Стандартный вывод
- Пример
- Стандартная ошибка
- Пример
- Перенаправление потока
- Пример
- Каналы
- Пример
- Пример
- Фильтры
- Пример
- Пример
- Заключение
- ИТ База знаний
- Полезно
- Навигация
- Серверные решения
- Телефония
- Корпоративные сети
- Использование потоков, конвейеров и перенаправлений в Linux
- Стандартный вывод ошибок.
- Конвейер
- Перенаправление ввода-вывода
- STDIN
- STDOUT
- STDERR
- Перенаправление вывода в скриптах
- Временное перенаправление вывода
- Постоянное перенаправление вывода
- Перенаправление ввода в скриптах
- Подавление вывода
- Перенаправление ввода-вывода в примерах Linux / Unix
- Что такое перенаправление?
- Перенаправление вывода
- Перенаправление ввода
- Дескрипторы файлов (FD)
- Перенаправление ошибок
- Почему перенаправление ошибок?
- Пример 1
- Пример 2
- Пример 3
- Операторы перенаправления вывода в Bash: что означает &1 и другие
- > /dev/null
- >(КОМАНДА) > /dev/null
Перенаправление ввода/вывода в Linux
Введение
Стандартные потоки ввода и вывода в Linux являются одним из наиболее распространенных средств для обмена информацией процессов, а перенаправление >, >> и | является одной из самых популярных конструкций командного интерпретатора.
В данной статье мы ознакомимся с возможностями перенаправления потоков ввода/вывода, используемых при работе файлами и командами.
Требования
Потоки
Стандартный ввод при работе пользователя в терминале передается через клавиатуру.
Стандартный вывод и стандартная ошибка отображаются на дисплее терминала пользователя в виде текста.
Ввод и вывод распределяется между тремя стандартными потоками:
Потоки также пронумерованы:
Из стандартного ввода команда может только считывать данные, а два других потока могут использоваться только для записи. Данные выводятся на экран и считываются с клавиатуры, так как стандартные потоки по умолчанию ассоциированы с терминалом пользователя. Потоки можно подключать к чему угодно: к файлам, программам и даже устройствам. В командном интерпретаторе bash такая операция называется перенаправлением:
Стандартный ввод
Стандартный входной поток обычно переносит данные от пользователя к программе. Программы, которые предполагают стандартный ввод, обычно получают входные данные от устройства типа клавиатура. Стандартный ввод прекращается по достижении EOF (конец файла), который указывает на то, что данных для чтения больше нет.
EOF вводится нажатием сочетания клавиш Ctrl+D.
Рассмотрим работу со стандартным выводом на примере команды cat (от CONCATENATE, в переводе «связать» или «объединить что-то»).
Cat обычно используется для объединения содержимого двух файлов.
Cat отправляет полученные входные данные на дисплей терминала в качестве стандартного вывода и останавливается после того как получает EOF.
Пример
В открывшейся строке введите, например, 1 и нажмите клавишу Enter. На дисплей выводится 1. Введите a и нажмите клавишу Enter. На дисплей выводится a.
Дисплей терминала выглядит следующим образом:
Для завершения ввода данных следует нажать сочетание клавиш Ctrl + D.
Стандартный вывод
Стандартный вывод записывает данные, сгенерированные программой. Когда стандартный выходной поток не перенаправляется в какой-либо файл, он выводит текст на дисплей терминала.
При использовании без каких-либо дополнительных опций, команда echo выводит на экран любой аргумент, который передается ему в командной строке:
Аргументом является то, что получено программой, в результате на дисплей терминала будет выведено:
При выполнении echo без каких-либо аргументов, возвращается пустая строка.
Пример
Команда объединяет три файла: file1, file2 и file3 в один файл bigfile:
Команда cat по очереди выводит содержимое файлов, перечисленных в качестве параметров на стандартный поток вывода. Стандартный поток вывода перенаправлен в файл bigfile.
Стандартная ошибка
Стандартная ошибка записывает ошибки, возникающие в ходе исполнения программы. Как и в случае стандартного вывода, по умолчанию этот поток выводится на терминал дисплея.
Пример
Рассмотрим пример стандартной ошибки с помощью команды ls, которая выводит список содержимого каталогов.
При запуске без аргументов ls выводит содержимое в пределах текущего каталога.
Введем команду ls с каталогом % в качестве аргумента:
В результате должно выводиться содержимое соответствующей папки. Но так как каталога % не существует, на дисплей терминала будет выведен следующий текст стандартной ошибки:
Перенаправление потока
Linux включает в себя команды перенаправления для каждого потока.
Пример
В приведенном примере команда cat используется для записи в файл file1, который создается в результате цикла:
Для завершения цикла нажмите сочетание клавиш Ctrl + D.
Если файла file1 не существует, то в текущем каталоге создается новый файл с таким именем.
Для просмотра содержимого файла file1 введите команду:
В результате на дисплей терминала должно быть выведено следующее:
Для перезаписи содержимого файла введите следующее:
Для завершения цикла нажмите сочетание клавиш Ctrl + D.
В результате на дисплей терминала должно быть выведено следующее:
Предыдущего текста в текущем файле больше не существует, так как содержимое файла было переписано командой >.
Для добавления нового текста к уже существующему в файле с помощью двойных скобок >> выполните команду:
Для завершения цикла нажмите сочетание клавиш Ctrl + D.
Откройте file1 снова и в результате на дисплее монитора должно быть отражено следующее:
Каналы
Каналы используются для перенаправления потока из одной программы в другую. Стандартный вывод данных после выполнения одной команды перенаправляется в другую через канал. Данные первой программы, которые получает вторая программа, не будут отображаться. На дисплей терминала будут выведены только отфильтрованные данные, возвращаемые второй командой.
Пример
В результате каждый файл текущего каталога будет размещен на новой строке:
Перенаправлять данные с помощью каналов можно как из одной команды в другую, так и из одного файла к другому, а перенаправление с помощью > и >> возможно только для перенаправления данных в файлах.
Пример
Для сохранения имен файлов, содержащих строку «LOG», используется следующая команда:
Вывод команды dir отсылается в команду-фильтр find. Имена файлов, содержащие строку «LOG», хранятся в файле loglist в виде списка (например, Config.log, Logdat.svd и Mylog.bat).
При использовании нескольких фильтров в одной команде рекомендуется разделять их с помощью знака канала |.
Фильтры
Фильтры представляют собой стандартные команды Linux, которые могут быть использованы без каналов:
Как правило, все нижеприведенные команды работают как фильтры, если у них нет аргументов (опции могут быть):
Если в качестве аргумента передается файл, команда-фильтр считывает данные из этого файла, а не со стандартного потока ввода (есть исключения, например, команда tr, обрабатывающая данные, поступающие исключительно через стандартный поток ввода).
Пример
Команда tee, как правило, используется для просмотра выводимого содержимого при одновременном сохранении его в файл.
Пример
Допускается перенаправление нескольких потоков в один файл:
В результате сообщение о неверной опции «z» в команде ls будет записано в файл t2, поскольку stderr перенаправлен в файл.
Для просмотра содержимого файла file3 введите команду cat:
В результате на дисплее терминала отобразиться следующее:
Заключение
Мы рассмотрели возможности работы с перенаправлениями потоков >, >> и |, использование которых позволяет лучше работать с bash-скриптами.
Источник
ИТ База знаний
Полезно
— Онлайн генератор устойчивых паролей
— Онлайн калькулятор подсетей
— Руководство администратора FreePBX на русском языке
— Руководство администратора Cisco UCM/CME на русском языке
— Руководство администратора по Linux/Unix
Навигация
Серверные решения
Телефония
FreePBX и Asterisk
Настройка программных телефонов
Корпоративные сети
Протоколы и стандарты
Использование потоков, конвейеров и перенаправлений в Linux
Работаем в командной строке
Операционные системы Unix традиционно используют такие понятия, как стандартный ввод, вывод и вывод ошибки. Чаще всего ввод — это клавиатура, а вывод это на кран. Но конечно же мы можем выводить исполнение какой-то команды в файл и передавать другой команде, потому что работая в Linux, создается такая последовательность из команд, т.е результат предыдущей мы отправляем следующей и т.д
Онлайн курс по Linux
Мы собрали концентрат самых востребованных знаний, которые позволят тебе начать карьеру администратора Linux, расширить текущие знания и сделать уверенный шаг к DevOps
Целью данной статьи является рассмотреть:
Стандартный вывод ошибок.
Следовательно, на экране мы уже не видим ошибки, потому что она отправилась в указанный файл.
Конвейер
Конвейер умеет передавать выходные данные из одной программы, как входные данные для другой. Т.е. выполняется команда, мы получаем результат и передаем эти данные далее на обработку другой программе.
Как видите после данной конструкции команд файлов не осталось. Т.е. данные построчно передались на команду удаления, которая построчно каждый файл с ключом –f (принудительно) их и удалила.
Источник
Перенаправление ввода-вывода
Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов. Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.
STDIN
STDOUT
STDERR
Если надо, STDERR и STDOUT можно перенаправить в один и тот же файл, воспользовавшись &> :
Устаревшая форма записи:
Оболочка определяет порядок перенаправления потоков в командной строке слева направо, поэтому приведенный выше пример нельзя записать так:
Для дозаписи в файл data-error.txt
Перенаправление вывода в скриптах
Существует два метода перенаправления вывода в сценариях командной строки:
Временное перенаправление вывода
Если запустить этот скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.
Запустим скрипт так, чтобы вывод STDERR попадал в файл:
Постоянное перенаправление вывода
Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять >&2 к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec :
Команду exec можно использовать не только в начале скрипта, но и в других местах:
Перенаправление ввода в скриптах
Для перенаправления ввода можно воспользоваться тем же способом, который использовался для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:
Подавление вывода
Вот, например, как подавить вывод сообщений об ошибках:
Тот же подход используется, если, например, надо очистить файл, не удаляя его:
Источник
Перенаправление ввода-вывода в примерах Linux / Unix
Что такое перенаправление?
Перенаправление — это функция Linux, позволяющая при выполнении команды изменять стандартные устройства ввода / вывода. Основной рабочий процесс любой команды Linux заключается в том, что она принимает входные данные и выдает выходные данные.
С перенаправлением можно изменить вышеуказанный стандартный ввод / вывод.
Перенаправление вывода
Символ ‘> ‘ используется для перенаправления вывода (STDOUT).
Перенаправление в Linux / Unix — раскрыто!

Примечание. Используйте правильное имя файла при перенаправлении вывода команды в файл. Если существует файл с таким же именем, перенаправленная команда удалит содержимое этого файла, а затем оно может быть перезаписано.
Если вы не хотите, чтобы файл был перезаписан, но хотите добавить больше содержимого в существующий файл, вам следует использовать оператор «>> ».

Вы можете перенаправить стандартный вывод не только в файлы, но и на устройства!
$ cat music.mp3> / dev / audio
Команда cat считывает файл music.mp3 и отправляет вывод в / dev / audio, которое является аудиоустройством. Если настройки звука на вашем ПК правильные, эта команда воспроизведет файл music.mp3
Перенаправление ввода
Символ ‘ 
Пример: почтовая программа в Linux может помочь вам отправлять электронные письма из Терминала.
Вы можете ввести содержимое электронного письма с помощью стандартной клавиатуры устройства. Но если вы хотите прикрепить файл к электронной почте, вы можете использовать оператор перенаправления ввода в следующем формате.

Это будет прикреплять файл с электронным письмом, и он будет отправлен получателю.
Приведенные выше примеры были простыми. Давайте посмотрим на некоторые передовые методы изменения направления, в которых используются файловые дескрипторы.
Дескрипторы файлов (FD)
В Linux / Unix все является файлом. Обычный файл, каталоги и даже устройства — это файлы. Каждый файл имеет связанный номер, называемый дескриптором файла (FD).
На вашем экране также есть дескриптор файла. Когда программа выполняется, вывод отправляется в файловый дескриптор экрана, и вы видите вывод программы на своем мониторе. Если выходные данные отправляются в файловый дескриптор принтера, выходные данные программы были бы напечатаны.
Перенаправление ошибок
Всякий раз, когда вы выполняете программу/команду на терминале, всегда открываются 3 файла, а именно: стандартный ввод, стандартный вывод, стандартная ошибка.

Эти файлы всегда присутствуют при запуске программы. Как объяснялось ранее, дескриптор файла связан с каждым из этих файлов.
| Файл | Дескриптор файла |
| Стандартный ввод STDIN | |
| Стандартный выход STDOUT | 1 |
| Стандартная ошибка STDERR | 2 |
По умолчанию на экране отображается поток ошибок. Перенаправление ошибок — это перенаправление ошибок в файл, отличный от экрана.
Почему перенаправление ошибок?
Перенаправление ошибок — одна из очень популярных функций Unix / Linux. Частые пользователи UNIX будут считать, что многие команды выдают огромное количество ошибок.
Решение — перенаправить сообщения об ошибках в файл.
Пример 1

Выше мы выполняем программу с именем myprogram.
Дескриптор файла для стандартной ошибки — 2.
Используя «2>», мы перенаправляем вывод ошибки в файл с именем «errorfile».
Таким образом, вывод программы не загроможден ошибками.
Пример 2
Вот еще один пример, в котором используется оператор поиска —
Используя команду «find», мы ищем «.» текущий каталог для файла с «именем», начинающимся с «my»

Пример 3
Давайте посмотрим на более сложный пример,
Администраторы сервера часто составляют списки каталогов и сохраняют как ошибки, так и стандартные выходные данные в файл, который можно обработать позже. Вот команда.
ls Documents ABC> dirlist 2> & 1
Источник
Операторы перенаправления вывода в Bash: что означает &1 и другие
Рассмотрим операторы перенаправления вывода Bash и похожие по функции операторы и конструкции. Я собрал следующий список, если что-то пропустил, то пишите в комментариях:
Этот оператор на английском называется pipe, и на русском его называют труба или конвейер. Используется очень часто для перенаправления вывода из одной команды в другую, которая может принимать стандартный вывод. Например:
Символ > используется для перенаправления вывода в файл, например:
То есть оператор | используется когда вывод передаётся в другую команду, а оператор > используется когда вывод записывается в файл.
Ещё один пример использования сразу обоих операторов:
Результат работы этой последовательности команд будет сохранён в файл num.txt.
Если файл не существует, то он будет создан. Если файл существует, то оператор > полностью удалит его содержимое и запишет новым.
> /dev/null
Это частный случай перенаправления, когда всё из стандартного вывода перенаправляется в псевдоустройство /dev/null. Это означает уничтожение данные. То есть ничего не будет выводиться в стандартный вывод.
Функция оператора >> похожа на > с тем отличием, что оператор >> не удаляет содержимое файла, а дописывает новые данные к уже существующим.
Если файл не существует, то оператор >> создаст его и запишет в него переданные данные.
Оператор 2> перенаправляет стандартный вывод ошибок — standard error (stderr).
Результат выполнения команд и возникшие ошибки выводятся на консоль и может показаться, что это одно и то же. Но на самом деле, это разные типы вывода.
К примеру попытаемся сохранить в файл текст ошибки, возникшей в результате выполнения команды:
Текст ошибки будет выведен на экран, но файл ls-error.txt окажется пустым.
Дело в том, что нужно различать стандартный вывод и стандартный вывод ошибок. Чтобы перенаправить стандартный вывод в файл используется оператор 2>:
В данном случае ошибка не будет выведена на экран, а будет сохранена в файл ls-error.txt.
Чтобы перенаправить стандартную ошибку, мы должны обратиться к её файловому дескриптору. Программа может выводить любой из нескольких пронумерованных файловых потоков. Первые три из этих файловых потоков называются стандартный ввод, стандартный вывод и стандартный вывод ошибок. Оболочка ссылается на них внутренне как файловые дескрипторы , 1 и 2 соответственно. Оболочка обеспечивает запись для перенаправления файлов с использованием номера дескриптора файла. Поскольку стандартная ошибка совпадает с дескриптором файла номер 2, мы можем перенаправить стандартную ошибку с помощью 2>.
Файловый дескриптор «2» помещается непосредственно перед оператором перенаправления, чтобы выполнить перенаправление стандартной ошибки в файл ls-error.txt.
Конструкция 2>&1 предназначена для перенаправления стандартного вывода и стандартного вывода ошибок в один файл.
В некоторых случаях мы можем захотеть записать весь вывод команды в один файл. Чтобы сделать это, мы должны одновременно перенаправить как стандартный вывод, так и стандартный вывод ошибок. Есть два способа сделать это. Во-первых, традиционный способ, который работает со старыми версиями оболочки:
Используя этот метод, мы выполняем два перенаправления. Сначала мы перенаправляем стандартный вывод в файл ls-output.txt, а затем перенаправляем дескриптор файла 2 (стандартная вывод ошибок) на дескриптор файла один (стандартный вывод), используя обозначения 2>&1.
Обратите внимание, что порядок перенаправлений является значимым. Перенаправление стандартной ошибки всегда должно происходить после перенаправления стандартного вывода, иначе оно не работает. В приведённом выше примере
перенаправляет стандартную ошибку в файл ls-output.txt, но при изменении порядка на
стандартная ошибка направлена на экран.
Последние версии bash предоставляют второй, более упрощённый метод для выполнения комбинированного перенаправления 2>&1:
В этом примере мы используем одинарную запись &> для перенаправления как стандартного вывода, так и стандартной ошибки в файл ls-output.txt.
Вы также можете добавить стандартные выходные данные и стандартные потоки ошибок в один файл, например так:
Итак, &> является аналогом 2>&1, а &>> это то же самое, но с перенаправлением вывода в файл.
Это ещё одна форма «подстановки процессов» (Process Substitution):
Если используется эта форма, то вместо записи в файл, данные будут переданы на ввод для КОМАНДЫ.
>(КОМАНДА) > /dev/null
Эка комбинация, включающая в себя 3 уже рассмотренных элемента:
Пример практического использования:
HTTP заголовки команда cURL выводит в stderr, а команда grep не ищет по stderr. Но если мы хотим искать только по HTTP заголовков (игнорируя HTML код), то мы не может сделать просто перенаправление stderr для слияния со стандартным выводом, то есть не можем 2>&1, поскольку текст страницы может содержать фразу «401 Unauthorized» и мы получим ложное срабатывание. Поэтому мы используем указанную выше конструкцию — стандартный вывод ошибок обрабатывается, стандартный вывод уничтожается.
Данная конструкция получает многострочный ввод по стандартному вводу и сохраняет его в файл. То есть это аналог
в котором просто операторы поменяны местами.
Источник
Модераторы: /dev/random, Модераторы разделов
-
pavelvat
- Сообщения: 64
- ОС: Arch Linux i686
find — каким ключом отключить сообщения «Отказано в доступе»?
Код: Выделить всё
[user@myhost ~]$ find / -name "*http_cache_*"
find: `/proc/tty/driver': Отказано в доступе
find: `/proc/1/task/1/fd': Отказано в доступе
find: `/proc/1/task/1/fdinfo': Отказано в доступе
find: `/proc/1/fd': Отказано в доступе
find: `/proc/1/fdinfo': Отказано в доступе
find: `/proc/2/task/2/fd': Отказано в доступе
.
.
.
/usr/share/kde4/services/http_cache_cleaner.desktop
.
.
.
find: `/usr/lib/mozilla/extensions': Отказано в доступе
.
.
.
/usr/lib/kde4/libexec/kio_http_cache_cleaner
/usr/lib/libkdeinit4_kio_http_cache_cleaner.so
find: `/lost+found': Отказано в доступе
find: `/boot/lost+found': Отказано в доступе
-
flank’er
- Сообщения: 496
- Статус: слаковщик
- ОС: Slackware64
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит…
- ОС: Slackware-current
- Контактная информация:
Re: find — каким ключом отключить сообщения «Отказано в доступе»?
Сообщение
drBatty » 02.02.2010 09:52
wilgib писал(а): ↑
02.02.2010 01:04
2 > /dev/null ?
Спасибо.
Но у этого способа есть недостаток — убираются все сообщения об ошибках, а нужно только не замусоривать вывод сообщениями о директориях к которым нет доступа. Я подумал, что разработчики find предусмотрели такую возможность, но беглый просмотр
как-бы это сообщение об ошибке, как его можно убрать? Я-бы тоже не стал так делать.
Впрочем лекарство есть:
запустите find с ключём -type d и проверяйте второй find только в директориях в которых у вас есть доступ. Впрочем, проще отфильтровать эти сообщения, как сказано в прошлом посте.
-
pavelvat
- Сообщения: 64
- ОС: Arch Linux i686
Re: find — каким ключом отключить сообщения «Отказано в доступе»?
Сообщение
pavelvat » 03.02.2010 12:23
drBatty писал(а): ↑
02.02.2010 09:52
wilgib писал(а): ↑
02.02.2010 01:04
2 > /dev/null ?
Спасибо.
Но у этого способа есть недостаток — убираются все сообщения об ошибках, а нужно только не замусоривать вывод сообщениями о директориях к которым нет доступа. Я подумал, что разработчики find предусмотрели такую возможность, но беглый просмотркак-бы это сообщение об ошибке, как его можно убрать? Я-бы тоже не стал так делать.
Впрочем лекарство есть:
запустите find с ключём -type d и проверяйте второй find только в директориях в которых у вас есть доступ. Впрочем, проще отфильтровать эти сообщения, как сказано в прошлом посте.
Пожалуй, способ указанный flank’er наиболее простой, но и у него есть недостаток — если локаль произвольная.
Всё же интересно, можно ли добиться желаемого только средствами команды find, без организации конвеера?
-
drBatty
- Сообщения: 8735
- Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит…
- ОС: Slackware-current
- Контактная информация:
Re: find — каким ключом отключить сообщения «Отказано в доступе»?
Сообщение
drBatty » 03.02.2010 12:46
wilgib писал(а): ↑
03.02.2010 12:23
если локаль произвольная.
Код: Выделить всё
drb@localhost:~$ ( LANG=C; find /etc -name "XXX" )
find: /etc/cups/ssl: Permission denied
find: /etc/samba/private: Permission denied
find: /etc/openvpn/certs: Permission denied
find: /etc/openvpn/keys: Permission denied
find: /etc/bluetooth/passkeys: Permission denied
drb@localhost:~$ find /etc -name "XXX"
find: /etc/cups/ssl: Отказано в доступе
find: /etc/samba/private: Отказано в доступе
find: /etc/openvpn/certs: Отказано в доступе
find: /etc/openvpn/keys: Отказано в доступе
find: /etc/bluetooth/passkeys: Отказано в доступе
wilgib писал(а): ↑
03.02.2010 12:23
Всё же интересно, можно ли добиться желаемого только средствами команды find, без организации конвеера?
ИМХО нет, разве что использовать -perm, -uid, что-бы не лазать в закрытые папки.
-
pavelvat
- Сообщения: 64
- ОС: Arch Linux i686
Re: find — каким ключом отключить сообщения «Отказано в доступе»?
Сообщение
pavelvat » 03.02.2010 15:11
drBatty писал(а): ↑
03.02.2010 12:46
wilgib писал(а): ↑
03.02.2010 12:23
если локаль произвольная.
Код: Выделить всё
drb@localhost:~$ ( LANG=C; find /etc -name "XXX" ) find: /etc/cups/ssl: Permission denied find: /etc/samba/private: Permission denied find: /etc/openvpn/certs: Permission denied find: /etc/openvpn/keys: Permission denied find: /etc/bluetooth/passkeys: Permission denied drb@localhost:~$ find /etc -name "XXX" find: /etc/cups/ssl: Отказано в доступе find: /etc/samba/private: Отказано в доступе find: /etc/openvpn/certs: Отказано в доступе find: /etc/openvpn/keys: Отказано в доступе find: /etc/bluetooth/passkeys: Отказано в доступе
Действительно, LANG=C решает проблему с произвольной локалью.
Для программирования сценариев на языке командного интерпретатора одной из важнейших его способностей является возможность организации сохранения результатов в файлы и возможность считывания исходных данных из файлов при выполнении команд.
командный интерпретатор организует перенаправления потоков ввода-вывода внешних и встроенных команд при помощи конструкций [n]>file или [n]>>file и [n]<file. Символы < и > естественным образом идентифицируют направление выполняемых перенаправлений — ввода или вывода, а необязательное число n уточняет номер перенаправляемого потока (при умалчивании n перенаправляется стандартный поток вывода № 1, stdout при выводе и стандартный поток ввода № 0, stdin при вводе). Перенаправление вывода > выполняется с усечением старого содержимого, а перенаправление >> — с добавлением к старому содержимому файла file.
Для перенаправления заданного потока N некоторой запускаемой команды command в файл file командный интерпретатор порождает дочерний процесс при помощи системного вызова fork, затем в новом процессе открывает файл file при помощи системного вызова open, перенаправляет поток N в открытый файл посредством системного вызова dup2 и, наконец, запускает в этом процессе программу command при помощи системного вызова execve.
В примере из листинга ниже при помощи «разрезателя» текста cut вырезается по разделителю (-d) : (двоеточие) 10-е поле (-f) файла passwd, содержащего свойства учетных записей пользователей, зарегистрированные в системе, а результат сохраняется в файле users при помощи перенаправления потока STDOUT. Затем, при помощи потокового редактора файлов sed выводятся (5,8р) только (-n) с 5-й по 8-ю строки полученного файла, что дает логины с 5-го по 8-го пользователей.
Содержимое
- Перенаправление стандартного потока вывода
- Перенаправление стандартного потока ошибок
- Подавление стандартного потока ошибок
- Перенаправление стандартного потока ввода
- Конвейерная обработка: отправка списка установленных пакетов по электронной почте
- Конвейерная обработка: подсчет количества пустых файлов
- Конвейерная обработка: вывод части файла
- Конвейерная обработка: генерация трех случайных восьмизначных паролей
- Конвейерная обработка: удаление пустых файлов
- Конвейерная обработка: просмотр группового членства пользователей системы
- Конвейерная обработка: параллельная упаковка ISO-образов
Перенаправление стандартного потока вывода
[email protected]:~$ sed -n 5,8р /etc/passwd
sync: х: 4:65534: sync: /bin: /bin/sync
games :х: 5:60: games: /usr/games: /bin/sh
man: х: 6:12: man: /var/cache/man: /bin/sh
lp: x: 7:7: lp: /var/spool/lpd: /bin/sh
[email protected]:~$ cut -f 1 -d : /etc/passwd 1> users
[email protected]:~$ sed -n 5,8p users
sync
games
man
lp
При выполнении некоторых команд, например как в листинге ниже, при поиске файлов посредством find может выводиться достаточное количество сообщений об «ошибках» доступа в тот или иной каталог, которые мешают анализировать результаты поиска.
В этом случае их удобно убрать с терминала путем перенаправления потока № 2, stderr, например, в файл eaccess. В результате на терминале будут отражены только имена (-name) файлов, соответствующие критерию имени *.xml, найденные в каталоге /etc и всех его подкаталогах.
Перенаправление стандартного потока ошибок
[email protected]:~$ find /etc -name ‘*.xml’
/etc/obex-data — server/imaging_capabilities. xml
find: ‘/etc/lvm/backup’: Отказано в доступе
find: ‘/etc/lvm/cache1: Отказано в доступе
find: ‘/etc/cups/ssl’: Отказано в доступе
/etc/ImageMagick/log. xml
[email protected]:~$ find /etc -name ‘*.xml’ 2>eaccess
/etc/obex-data-server/imaging_capabilities.xml
/etc/ImageMagick/log. xml
На практике часто оказывается; что мешающий вывод сообщений об «ошибках» доступа, как в листинге ниже, оказывается ненужным вовсе, тогда его подавляют при помощи перенаправления потока STDERR в файл /dev/null специального всепожирающего псевдоустройства null.
Подсчитав количество строк (-l) в результирующем файле empty и зная, что одна строка в нем соответствует одному найденному ранее командой find имени файла, размер (-size) которого равен 0 байт, можно получить количество «пустых» файлов в системе.
Подавление стандартного потока ошибок
В случаях, когда необходимо использовать содержимое файла в качестве исходных данных для выполнения -программ, вместо ввода этих данных с терминала, как в примере из листинга ниже, применяют перенаправление потока STDIN. Таким образом, например, сохраненный в файл весьма внушительный список установленных в системе пакетов (полученный командой dpkg) можно отправить по почте командой mail в качестве текста сообщения.
Перенаправление стандартного потока ввода
Однако чаще на практике необходимо использовать результат выполнения одной команды в качестве исходных данных другой команды, не сохраняя, эти данные в промежуточный (ненужный) файл. В. этом случае используют конструкциюcommand1 | command2 | называемую конвейерной обработкой (или просто конвейером, или каналом (pipe), или даже трубой).
Нужно заметить, конструкцией конвейерной обработки можно сцеплять более чем две команды, причем все они будут выполняться параллельно в дочерних процессах командного интерпретатора. При этом стандартные потоки ввода и вывода пар процессов будут связаны простейшим средством IPC, реализуемым ядром ОС — неименованным каналом, создаваемым системным вызовом pipe, куда и будут перенаправлены потоки команд при помощи системного вызова dup2.
При использовании конвейерной обработки в примере из листинга ниже отправка списка пакетов, установленных в системе почтовым сообщением, происходит без промежуточного файла, ровно как и подсчет количества файлов, размер которых равен 0 байт.
Конвейерная обработка: отправка списка установленных пакетов по электронной почте
Конвейерная обработка: подсчет количества пустых файлов
Конвейерная обработка: вывод части файла
[email protected]:~$ getent passwd | cut -f 1 -d : | head -8 | tail -5
sys
sync
games
man
lp
В примере из листинга выше конвейерная обработка используется для последовательного получения строкового представления свойств всех доступных пользовательских учетных записей при помощи getent, затем вырезания из этих строк при помощи cut 1-го поля (-f) посредством разделителя : (-d), далее выбора 8-ми первых строк командой head, а потом выбора 5-ти последних строк предыдущего результата командой tail. Учетные записи пользователей, зарегистрированных непосредственно в системе (локально), хранятся в файле /etc/passwd. Все доступные в системе учетные записи, в том числе, например, централизованные в (сетевых) LDAP-каталогах организации, могут быть получены при помощи команды getent благодаря службе имен.
Конвейерная обработка: генерация трех случайных восьмизначных паролей
[email protected]:~$ tr -dc a-zA-ZO-9 </dev/urandom | fold -w 8 | head -3
QCh67VnC
3nwAG7P9
51IС1Lxz
В листинге выше конвейерная обработка в совокупности с перенаправлением потока STDIN используется для генерации трех случайных строк, которые могут использоваться, например, в качестве начальных паролей пользовательских учетных записей.
Для этого из специального файла псевдоустройства urandom, генерирующего случайную последовательность байтов, отбираются командой транслитерации tr только строковые и заглавные буквы латинского алфавита и цифры a-zA-z0-9 путем удаления (-d) из выходного потока символов, не (-с) попавших в заданный набор. Затем команда fold разбивает свой входной поток по 8 символов в строке выходного потока, после чего команда head выбирает только 3 первые строки.
Конвейерная обработка: удаление пустых файлов
[email protected]:~$ find /tmp -user bender -size 0 -print0 2>/dev/null | xargs -0 rm -f
В листинге выше конвейерная обработка вместе с командой xargs используется для того, чтобы во временном каталоге /tmp удалить все файлы, принадлежащие (-user) пользователю bender, размер (-size) которых равен нулю. Сначала при помощи команды find производится поиск файлов согласно указанным критериям и вывод списка их имен с разделением имен нулевым символом (-print).
Затем команда xargs последовательно «применяет» команду rm безусловного (-f) удаления файла для каждого имени из списка. Следует отметить, что такая конструкция работает с абсолютно любыми именами файлов, включая файлы с пробелами, табуляциями, переводами строк и другими управляющими символами в имени, т. к. имена файлов в списке разделяются нулевым символом, а он единственный запрещен к использованию в именах файлов.
Аналогично, в листинге ниже, используя конвейер, при помощи команды groups можно вывести групповое членство всех пользователей, доступных в системе.
Конвейерная обработка: просмотр группового членства пользователей системы
[email protected]:~$ getent passwd | cut -f 1 -d : | xargs groups
john : john candy
mike : mike
bubble : bubble candy
fitz : fitz sudo
skillet : skillet
bender : bender
С помощью конвейеров и универсального спискового «применятеля» команд xargs можно организовать параллельный запуск (-Р) упаковки целого списка отобранных командой find файлов, использовав параллельный упаковщик pbzip2, в несколько упаковочных нитей (-р) на каждый файл. В результате получим запускаемые парами процессы по две активные нити на каждый, что эффективно загружает четырехъядерный процессор в течение упаковки всего списка файлов.
Конвейерная обработка: параллельная упаковка ISO-образов
[email protected]: ~$ find . -name ‘*.iso’ ( xargs -P 2 pbzip2 -p2 &
[email protected]: ~$ ps f
PID TTY STAT TIME COMMAND
4723 pts/1 S 0:00 -bash
4903 pts/1 S 0:00 _ xargs -P 2 -nl pbzip2 -p2
4904 pts/1 Sl 0:08, | _ pbzip2 -p2 ./dvd.itso
4905 pts/1 Sl 0:08 | _ pbzip2 -p2 ./plan9.iso
4856 pts/1 R+ 0:00 _ ps f
[email protected]: ~$ ps -fL
UID PID PPID LWP C NLWP STIME TTY TIME CMD
bender 4723 4722 4723 0 1 01:18 pts/1 00:00:00 -bash
bender 4903 4723 4903 0 1 01:21 pts/1 00:00:00 xargs -P 2 -nl pbztp2
bender 4904 4903 4910 99 6 01:21 pts/1 00:00:01 pbzip2 -p2 ./dvd.tso
bender 4904 4903 4913 99 6 01:21 pts/1 00:00:01 pbztp2 -p2 ./dvd.tso
bender 4904 4903 4914 0 6 01:21 pts/1 00:00:00 pbztp2 -p2 ./dvd.tso
bender 4905 4903 4911 99 0 01:21 pts/1 00:00:01 pbztp2 -p2 ./plan9.ts
bender 4905 4903 4912 99 6 01:21 pts/1 00:00:01 pbztp2 -p2 ./plan9.ts
bender 4905 4903 4915 0 6 01:21 pts/1 00:00:00 pbztp2 -p2 ./plan9.ts
bender 4916 4723 4916 0 1 01:21 pts/1 00:00:00 ps -fL
0
2
Всех приветствую, нужна помощь с скриптом.
ОС Alt Linux Рабочая станция
Linux host-15tstalt 5.10.128-std-def-alt1 #1 SMP Fri Jul 8 14:39:36 UTC 2022 x86_64 GNU/Linux
Имеется скрипт с таким содержимым.
#! /bin/bash
source /media/dirlab/coutlistuser
find /media/dirlab -user $43 -exec sh -c "file '{}' | grep -q 'ELF'" ; -print | wc -l
Файл /media/dirlab/coutlistuser это автоматически генерируемый файл с содержимым по пользователям. Нужен для того что бы проверять появились пользователи новые или нет.
Выглядит примерно так
p1=polkitd
p2=_avahi
p3=_ldm
p4=_chrony
.....
p49=mxvel
p50=ivanov
p51=petrov
p52=sidorov
p53=pupkin
find /media/dirlab — поиск в нужном нам каталоге
-user $43 -exec sh -c «file ‘{}’ | grep -q ‘ELF’» ; -print — условие при котором происходит поиск исполняемых ELF файлов по владельцам. Источник с пользователями как раз для этого.
-print | wc -l — вывод численного количества ELF файлов.
Возникает несколько ошибок/задач которые не знаю как исправить.
- Если переменная с пользователями ($p54 и больше) превышает количество существующих пользователей в системе появляется ошибка
find: ‘-exec’ is not the name of a known user
Понятно почему появляется, но нужно что бы информация о несуществующем пользователе не выводилась.
- Если пользователь существует но нет файлов ELF в каталоге скрипт указывает количество файлов
Это пустое количество тоже выводить не нужно.
Пробовал обернуть это в значения «если то»
#!/bin/bash
source /media/dirlab/coutlistuser
if
COUNT=`find /media/dirlab -user $p51 -exec sh -c "file '{}' | grep -q 'ELF'" ; -print | wc -l `
then [ $COUNT -eq 0 ]
else
echo "$p51 $COUNT"
fi
Но вывод информации вообще перестает происходить даже если ELF файлы есть.
Кто знает как сделать 1 и 2 пункт?
Всё в Linux — это файлы, в том числе — ввод и вывод. Операционная система идентифицирует файлы с использованием дескрипторов. Каждому процессу позволено иметь до девяти открытых дескрипторов файлов. Оболочка bash резервирует первые три дескриптора с идентификаторами 0, 1 и 2. Вот что они означают.
- 0, STDIN — стандартный поток ввода
- 1, STDOUT — стандартный поток вывода
- 2, STDERR — стандартный поток ошибок
STDIN
STDIN — это стандартный поток ввода оболочки. Для терминала стандартный ввод — это клавиатура. Когда используется символ перенаправления ввода — <, Linux заменяет дескриптор файла стандартного ввода на тот, который указан в команде. Система читает файл и обрабатывает данные так, будто они введены с клавиатуры.
Многие команды bash принимают ввод из STDIN, если в командной строке не указан файл, из которого надо брать данные. Например, это справедливо для команды cat.
Когда вы вводите команду cat в командной строке, не задавая параметров, она принимает ввод из STDIN. После того, как вы вводите очередную строку, cat просто выводит её на экран. И останавливается после того как получает EOF. EOF вводится нажатием сочетания клавиш Ctrl+D.
STDOUT
STDOUT — стандартный поток вывода оболочки. По умолчанию это — экран. Большинство bash-команд выводят данные в STDOUT, что приводит к их появлению в консоли. Данные можно перенаправить в файл, для этого используется символ перенаправления вывода >.
Можно осуществить перенаправление вывода в файл с добавлением в конец с помощью >>. При этом информация, хранящаяся в файле не будет удалена, а вся новая информация будет добавлена в конец этого файла.
STDERR
STDERR представляет собой стандартный поток ошибок оболочки. По умолчанию этот дескриптор указывает на то же самое, на что указывает STDOUT, именно поэтому при возникновении ошибки мы видим сообщение на экране.
Рассмотрим простой пример — нужно записать в файл data.txt содержимое директории data. Если директория не существует, сообщение об ошибке надо записать в файл error.txt. Чтобы этого добиться, нужно использовать команды перенаправления для соответствующих дескрипторов с указанием файлов, куда должны попадать ошибки и стандартный вывод:
$ ls data 1> data.txt 2> error.txt
Если надо, STDERR и STDOUT можно перенаправить в один и тот же файл, воспользовавшись &>:
$ ls data &> data-error.txt
Устаревшая форма записи:
$ ls data > data-error.txt 2>&1
Оболочка определяет порядок перенаправления потоков в командной строке слева направо, поэтому приведенный выше пример нельзя записать так:
$ ls data 2>&1 > data-error.txt
В этом случае сначала вывод ошибок перенаправляется в стандартный вывод (на экран), а потом стандартный вывод перенаправляется в файл data-error.txt. То есть, ошибки будут выведены в консоль, а данные — в файл.
Для дозаписи в файл data-error.txt
$ ls data &>> data-error.txt
Перенаправление вывода в скриптах
Существует два метода перенаправления вывода в сценариях командной строки:
- Временное перенаправление, или перенаправление вывода одной строки
- Постоянное перенаправление, или перенаправление всего вывода сценария
Временное перенаправление вывода
В сценарии можно перенаправить вывод отдельной строки в STDERR. Чтобы это сделать, достаточно использовать команду перенаправления, указав дескриптор STDERR, при этом перед номером дескриптора надо поставить символ амперсанда:
#!/bin/bash echo "This is an error" >&2 echo "This is normal output"
Если запустить этот скрипт, обе строки попадут на экран, так как, как вы уже знаете, по умолчанию ошибки выводятся туда же, куда и обычные данные.
$ ./test.sh This is an error This is normal output
Запустим скрипт так, чтобы вывод STDERR попадал в файл:
$ ./test.sh 2> error.txt This is normal output $ cat error.txt This is an error
Теперь обычный вывод делается в консоль, а сообщения об ошибках попадают в файл error.txt.
Постоянное перенаправление вывода
Если в скрипте нужно перенаправлять много выводимых на экран данных, добавлять >&2 к каждому вызову echo неудобно. Вместо этого можно задать перенаправление вывода в определённый дескриптор на время выполнения скрипта, воспользовавшись командой exec:
#!/bin/bash exec 1> output.txt echo "Это пример перенаправления всего" echo "вывода сценария в файл output.txt" echo "без перенаправления каждой строки"
После запуска сценария весь вывод будет перенаправлен в файл output.txt.
Команду exec можно использовать не только в начале скрипта, но и в других местах:
#!/bin/bash # ошибки перенаправляем в файл error.txt exec 2> error.txt # строка будет выведена на экран echo "Первый вывод сценария" # перенаправляем вывод в файл output.txt exec 1> output.txt # строка будет записана в файл output.txt echo "Второй вывод сценария" # строка будет записана в файл error.txt echo "Третий вывод сценария" >&2
Перенаправление ввода в скриптах
Для перенаправления ввода можно воспользоваться тем же способом, который использовался для перенаправления вывода. Например, команда exec позволяет сделать источником данных для STDIN какой-нибудь файл:
$ exec 0< data.txt
Эта команда указывает оболочке на то, что источником вводимых данных должен стать файл data.txt, а не обычный STDIN. Посмотрим на перенаправление ввода в действии:
#!/bin/bash exec 0< data.txt count=1 while read line ; do echo "Line #$count: $line" count=$(( $count + 1 )) done
Подавление вывода
Иногда надо сделать так, чтобы команды в скрипте, который, например, может исполняться как фоновый процесс, ничего не выводили на экран. Для этого можно перенаправить вывод в /dev/null.
Вот, например, как подавить вывод сообщений об ошибках:
$ ls -al badfile.txt file.txt 2> /dev/null
Тот же подход используется, если, например, надо очистить файл, не удаляя его:
$ cat /dev/null > data.txt
Поиск:
Bash • CLI • Linux • stderr • stdin • stdout • Поток
Да я же знал и про перенаправление, и про /dev/null
Но вот так работают шаблоны мышления — искал соответствующий параметр у программы, а посмотреть на проблему с другой стороны не сообразил..
Но вот с таким еще не встречался, спасибо:
Цитировать
&>файл — перенаправить стандартный вывод (stdout) и ошибки в файл
2>&1 | tee файл — копировать вывод ошибок в stdout, показывать на экране и одновременно писать в файл
