The behaviour you are describing is caused by a bug in netrw, which is the plugin handling the file browsing.
Updating to the latest version of the plugin fixes this behaviour.
To do so, just download the latest version of netrw, open it in vim and source it. Doing so will extract the plugin into your ~/.vim
directory, where it will be loaded before the system's buggy version.
Download the file:
wget http://www.drchip.org/astronaut/vim/vbafiles/netrw.vba.gz
Open it in vim
:
vim netrw.vba.gz
In vim, source it:
:so %
Afterwards, close vim. Then, enjoy browsing directories again.
Update: On one box, this gave me an error about not being able to close the last window. Had no effect on the plugin, which worked flawlessly afterwards.
2nd Update: This version of netrw expects a version of vim with the clipboard capability.
You can check if your version has it by running vim --version
. The output will probably have -clipboard
in there, which means the capability is not enabled.
To get a version compiled with clipboard support, install any version of vim with a GUI, which will also replace your normal vim
with a version with clipboard support. I used vim-gtk as a test case.
That's the trick: command doesn't know, it's the shell that does the job
Consider for example grep 'abc' *.txt
. If we run trace of system calls, you will see something like this:
bash-4.3$ strace -e trace=execve grep "abc" *.txt > /dev/null
execve("/bin/grep", ["grep", "abc", "ADDA_converters.txt", "after.txt", "altera_license.txt", "altera.txt", "ANALOG_DIGITAL_NOTES.txt", "androiddev.txt", "answer2.txt", "answer.txt", "ANSWER.txt", "ascii.txt", "askubuntu-profile.txt", "AskUbuntu_Translators.txt", "a.txt", "bash_result.txt", ...], [/* 80 vars */]) = 0
+++ exited with 0 +++
The shell expanded *.txt
into all filenames in current directory that end with .txt
extension. So effectively, your shell translates the grep 'abc' *.txt
command into grep 'abc' file1.txt file2.txt file3.txt . . .
. Thus, your second assumption is correct.
First assumption is not correct - programs have no way of detecting glob. It is possible to pass *
as string argument to command, but it's the command's job to decide what to do with it then. Filename expansion, however, is property of your respective shell as I've already mentioned.
However, this only works because grep accepts multiple files at the end. It is possible that another command would only allow 1 file to be passed in.
Exactly right ! Programs don't limit the number of acceptable command-line arguments (for instance , in C that's array of strings const char *args[]
and in python sys.argv[]
), but they can detect the length of that array or whether or not something unexpected is in wrong array position. grep
doesn't do that, and accepts multiple files, which is by design.
On side note , improper quoting coupled with globbing with grep can sometimes be a problem. Consider this:
bash-4.3$ echo "one two" | strace -e trace=execve grep *est*
execve("/bin/grep", ["grep", "self_test.sh", "test.wxg"], [/* 80 vars */]) = 0
+++ exited with 1 +++
Unprepared user would expect that grep will match any line with est
letters in it coming from pipe, but instead shell's filename expansion twisted everyting around. I've seen this happen a lot with people who do ps aux | grep shell_script_name.sh
, and they expect to find their process running, but because they ran command from same directory where script was, shell's filename expansion made grep
command to look completely different behind the scenes from what user expected.
Proper way would be to use single quotes:
bash-4.3$ echo "one two" | strace -e trace=execve grep '*est*'
execve("/bin/grep", ["grep", "*est*"], [/* 80 vars */]) = 0
+++ exited with 1 +++
Best Answer
You are using two different things here and should be using a third. Let's see:
|
: This is the pipe operator, it serves to pass the output of one process as input to another:This runs the program
foo
and passes its output as input to the programbar
.>
,<
,>>
and<<
: These are the redirection operators, they serve to send data to/from files:foo > bar
: runs the programfoo
and saves its output to the filebar
, overwriting1 its contents and creating it if it does not exist.foo >> bar
: runs the programfoo
and saves its output to the filebar
, appending to its contents and creating it if it does not exist.foo < bar
: runsfoo
, telling it to read input from the filebar
.The
<<
is a special case, since there is no point in "appending" input to a command, the<<
is primarily (exclusively AFAIK) used for Here Documents:The construct
<< SomeStringHere > Out.file
will redirect all text written until it encounters the ending string (EOF
in the example above) to the target file. Here docs allow you to easily format multi-line strings and include variables and special characters.The
<<<
operator, the Here String, is like a Here Document but it expands variables. So, for example:The command above is equivalent to
echo "$bar" | grep foo
.What you are actually looking for is called process substitution and is another way to pass the output of a command to another. It consists of
<(command)
.So, for your
at
example, you could doThe above works because process substitution actually creates a file (read the link above for more details) and it is the file descriptor of that file that is passed with
<
toat now
.1 The default behavior is to overwrite, this can be modified by setting the
noclobber
option to bash. If set,echo foo > bar
will fail ifbar
exists. In that case, it can be forced usingecho foo |> bar
instead. See section 3.6.2 here.