В bash пустая команда с перенаправлением просто открывает файл способом, связанным с перенаправлением, а затем закрывает его *. echo "hello" >&0 | > file.txt представляет собой составную команду, состоящую из двух простых команд: echo "hello" >&0, > file.txt, pipeed. Вторая команда пуста, поэтому bash просто открывает файл для записи, обрезает его и закрывает.
В терминале обычно подключаются стандартный вывод, вывод и ошибка. Поэтому, когда вы перенаправляете stdout на stdin, он все еще указывает на терминал, а вывод echo hello >&0 отображается в терминале и вообще не отправляется в канал.
В zsh пустая команда с перенаправлением по умолчанию имеет cat команду. Таким образом, echo "hello" >&0 | > file.txt эффективно echo "hello" >&0 | cat > file.txt, и вы увидите эффект, который вы хотите. Это невозможно в bash. Здесь вы увидите другую функцию перенаправления, которая не видна в bash: когда вы перенаправляете вывод команды несколько раз, вывод отправляется каждому из перенаправленных адресатов (поэтому hello отправляется как на терминал, так и на труба). В bash он отправляется только в последнее перенаправленное местоположение.
* Исключение составляет пустая команда с перенаправлением с перенаправленным stdin. В $(
grep с флагом -r рекурсивно работает со всеми файлами в указанных каталогах:
-r, --recursive
Read all files under each directory, recursively, following
symbolic links only if they are on the command line. Note that
if no file operand is given, grep searches the working
directory. This is equivalent to the -d recurse option.
По умолчанию, если каталоги не указаны, тогда grep будет обрабатывать все файлы в текущий каталог.
В grep -r ... * оболочка расширяет * ко всем файлам и каталогам в текущем каталоге (обычно, кроме тех, которые начинаются с .) и grep затем работает рекурсивно на них.
Итак, если у вас есть каталог, содержащий, например:
.git/
.gitignore
foo/
foo/.foo2
foo/link2 -> /foo2/bar2
bar
link1 -> /foo/bar
, где имена, заканчивающиеся на /, являются каталогами, тогда также будет обрабатывать файл .gitignore и все в .git, но grep -r ... * будет exand grep -r ... foo bar, и в итоге будет исключать .gitignore и .git (но он будет включать foo/.foo2). [ ! d5]
Также обратите внимание на точку символических ссылок - если один из файлов в расширении * был символической ссылкой, цель symlink будет обработана, если вы использовали *. Таким образом, с *, /foo/bar будет обрабатываться как цель link1, но не /foo2/bar2 в качестве цели link2.
Общий эффект:
Что вы хотите сделать, конечно, зависит от того, хотите ли вы, чтобы эти файлы и каталоги включались в поиск; но я предпочитаю, чтобы grep сам делал исключение и включал использование --exclude / --include и других опций.
grep с флагом -r рекурсивно работает со всеми файлами в указанных каталогах:
-r, --recursive
Read all files under each directory, recursively, following
symbolic links only if they are on the command line. Note that
if no file operand is given, grep searches the working
directory. This is equivalent to the -d recurse option.
По умолчанию, если каталоги не указаны, тогда grep будет обрабатывать все файлы в текущий каталог.
В grep -r ... * оболочка расширяет * ко всем файлам и каталогам в текущем каталоге (обычно, кроме тех, которые начинаются с .) и grep затем работает рекурсивно на них.
Итак, если у вас есть каталог, содержащий, например:
.git/
.gitignore
foo/
foo/.foo2
foo/link2 -> /foo2/bar2
bar
link1 -> /foo/bar
, где имена, заканчивающиеся на /, являются каталогами, тогда grep -r также будет обрабатывать файл .gitignore и все в .git, но grep -r ... * будет exand grep -r ... foo bar, и в итоге будет исключать .gitignore и .git (но он будет включать foo/.foo2). [ ! d5]
Также обратите внимание на точку символических ссылок - если один из файлов в расширении * был символической ссылкой, цель symlink будет обработана, если вы использовали *. Таким образом, с *, /foo/bar будет обрабатываться как цель link1, но не /foo2/bar2 в качестве цели link2.
Общий эффект:
w/o * with *
.git/ + -
.gitignore + -
foo/ + +
foo/.foo2 + +
foo/link2 -> /foo2/bar2 - -
bar + +
link1 -> /foo/bar - +
Что вы хотите сделать, конечно, зависит от того, хотите ли вы, чтобы эти файлы и каталоги включались в поиск; но я предпочитаю, чтобы grep сам делал исключение и включал использование --exclude / --include и других опций.
grep с флагом -r рекурсивно работает со всеми файлами в указанных каталогах:
-r, --recursive
Read all files under each directory, recursively, following
symbolic links only if they are on the command line. Note that
if no file operand is given, grep searches the working
directory. This is equivalent to the -d recurse option.
По умолчанию, если каталоги не указаны, тогда grep будет обрабатывать все файлы в текущий каталог.
В grep -r ... * оболочка расширяет * ко всем файлам и каталогам в текущем каталоге (обычно, кроме тех, которые начинаются с .) и grep затем работает рекурсивно на них.
Итак, если у вас есть каталог, содержащий, например:
.git/
.gitignore
foo/
foo/.foo2
foo/link2 -> /foo2/bar2
bar
link1 -> /foo/bar
, где имена, заканчивающиеся на /, являются каталогами, тогда grep -r также будет обрабатывать файл .gitignore и все в .git, но grep -r ... * будет exand grep -r ... foo bar, и в итоге будет исключать .gitignore и .git (но он будет включать foo/.foo2). [ ! d5]
Также обратите внимание на точку символических ссылок - если один из файлов в расширении * был символической ссылкой, цель symlink будет обработана, если вы использовали *. Таким образом, с *, /foo/bar будет обрабатываться как цель link1, но не /foo2/bar2 в качестве цели link2.
Общий эффект:
w/o * with *
.git/ + -
.gitignore + -
foo/ + +
foo/.foo2 + +
foo/link2 -> /foo2/bar2 - -
bar + +
link1 -> /foo/bar - +
Что вы хотите сделать, конечно, зависит от того, хотите ли вы, чтобы эти файлы и каталоги включались в поиск; но я предпочитаю, чтобы grep сам делал исключение и включал использование --exclude / --include и других опций.