Narrowly Addressing The Problem: With Readlink
Since you're on Ubuntu (which has GNU readlink), you can use readlink -e
, which has the exact behavior you're hoping that realpath
will provide:
git diff --name-only master... \
| xargs -d $'\n' readlink -e -- \
| xargs -d $'\n' someEditor
Since you're on Ubuntu, which provides GNU xargs, this code will correctly handling filenames with spaces, literal quotes, or literal backslashes on account of using -d $'\n'
on both xargs
invocations.
Narrowly Addressing The Problem: With Realpath
If we want to stick with your existing tools (which is to say, realpath
instead of readlink
) and just add an existence test, that could look like:
git diff --name-only master... \
| xargs -d $'\n' sh -c 'for f; do [ -e "$f" ] && realpath "$f"; done' _ \
| xargs -d $'\n' someEditor
Implementation Advice
By the way -- consider encapsulating your desired implementation in a shell function in your ~/.bashrc
. That might be something like...
forEachChangedFile {
local -a files
readarray -t files < <(
git diff --name-only "${branchExpr:-master...}" \
| xargs -d $'\n' readlink -e --
)
if (( $# )); then
"$@" "${files[@]}"
else
"${EDITOR:-someEditor}" "${files[@]}"
fi
}
...later used as:
forEachChangedClient vim
or
branchExpr=someBranch..someOtherBranch forEachChangedFile emacs-client
The advantage of not using xargs
for the final invocation of the editor is that it leaves the editor's stdin clear, so you can use it for editors that communicate with the user over that channel.