0

I have a file which contains whitespace in its name: my file.txt.

If I want to find a file which has this name and pipe its output to a vim with args, I must use --null|-0 in order to handle whitespace correctly:

find . -iname "my*file.txt" | xargs --null vim

The problem is that the filename that is passed to the command is my file.txt^@.

The ^@ is the null character in vim.

So how can I pass the my file.txt file from find or fzf to vim ?

1
  • Whitespace is just fine in most situations -- it just needs quoting, and your code will fail because shell actually searches for filenames containing literally * ,because it does not expand * inside quotes. NUL is entirely different to whitespace. Commented Jan 19 at 10:11

2 Answers 2

3

Normally, you don't. I mean sure, you can play around with -print0 and then -0 with xargs, but why? Just use find's -exec option which is designed for this sort of thing. From man find:

-exec command ;

Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ; is encountered.

So you can just do this to open one file:

find . -iname 'my*file.txt' -exec vim {} \;

Or, if can you have many matching files and want to open all of them:

-exec command {} +

This variant of the -exec action runs the specified command on the selected files, but the command line is built by appending each selected file name at the end; the total number of invocations of the command will be much less than the number of matched files. The command line is built in much the same way that xargs builds its command lines.

In your case, that would look like this:

find . -iname 'my*file.txt' -exec vim {} +

If you had to use xargs and your xargs happened to be the one from GNU findutils, from a shell with support for Korn-style process substitution, the equivalent would look like:

xargs -r0a <(find . -iname 'my*file.txt' -print0) vim

Where:

  • we use -print0 to match the format expected by xargs -0 (standard equivalent of xargs --null).
  • we use -r to avoid running vim without argument if there's no matching file.
  • we pass the list as a file (here a sort-of-named-pipe) argument to -a instead of xargs stdin so as to preserve vim's stdin.
0
0

find's separator is by default a newline \n.

From the man page:

-print

True; print the full file name on the standard output, followed by a newline. (...)

So you must either

  1. Tell xargs to use \n as separator:
    find . -iname "my*file.txt" | xargs -d "\n" vim
    
  2. or tell find to use null character as separator:
    find . -iname "my*file.txt" -print0 | xargs --null vim
    

Again, from the man page:

-print0

True; print the full file name on the standard output, followed by a null character (instead of the newline character that -print uses). This allows file names that contain newlines or other types of white space to be correctly interpreted by programs that process the find output. This option corresponds to the -0 option of xargs.

1
  • If you care about standards and portability, use the standard -0 option with xargs rather than the GNU --null extension to the standard.
    – Kusalananda
    Commented Jan 19 at 8:11

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.