How to edit a list of generated files whose names contain spaces
Since you are in Bash,
#!/bin/bash
readarray -d '' -t files < <(find path -type f -print0)
vi -- "${files[@]}"
Replace find path -type f -print0
with your actual pipeline.
Although your files have no newlines, the support for such filenames has been added by user glenn jackman.
To use tabs instead of buffers for vi
, add the -p
flag: vi -p ...
.
If the pipeline was not required, you could straighforwardly use the -exec
option:
find path -type f -exec vi -- {} +
Unfortunately this does not work when mycommand is an editor because although xargs can assemble the set of files to edit, stdin is already taken up from the pipeline and I can't see a way to run an editor in-place.
That way is documented in the manual page for the GNU Findutils xargs
:
-o, --open-tty
Reopen stdin as /dev/tty in the child process before executing
the command. This is useful if you want xargs to run an inter‐
active application.
So that you could use
find . -name 'pattern' -print0 | xargs -0o vim
However, it is a newer feature. I don't see it in an older system that has xargs 4.4.2; I see it on Ubuntu 18, which has xargs 4.7.0.
Now xargs
may not have had the -o
option ten years ago, but Bash process substitution existed ten years ago, and xargs
has the -a
option to read from a file instead of standard input.
So the problem is solvable without xargs -o
like this:
xargs -0 -a <(find . -name 'pattern' -print0) vim
Because xargs
is reading from (what it thinks is) a file that it received as an argument, it has left standard input alone.
From the comments I get something similar like this is your command:
find -type f -mtime +14 -mtime -22 -iname '*.xml' | while IFS= read -f x; do xmlstarlet sel -T -t -v '//magicElement' -n "$x" | grep -q magicValue && echo "$x"; done
Instead of piping to a while
- loop you could use -exec sh -c '...'
to filter files:
find -type f -mtime +14 -mtime -22 -iname '*.xml' \
-exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
-exec vi -- {} +
Try:
Consider three files:
.
├── a:<magicElement>magicValue</magicElement>
├── b:<magicElement>magicValue</magicElement>
└── c:<magicElement>someOtherValue</magicElement>
$ find . -type f \
-exec sh -c 'xmlstarlet sel -T -t -v "//magicElement" "$1" | grep -q magicValue' find-sh {} \; \
-exec echo vi -- {} +
Output:
vi -- ./a ./b