I'm search for a function for bash that will escape a filename the same way "tab" escapes filenames.
Solution to get escaped full paths
I've created a portable function to get all the escaped paths to all items in the current directory, tested on macOS and Linux (requires GNU bash installed).
escpaths() {
find "$PWD" -maxdepth 1 -print0 | xargs -0 -I {} bash -c 'printf "%q\n" "$0"' {} | sort
}
Here's a rigorous test case scenario:
# Generate test directory, containing test directories and files.
mkdir 'test dir'; cd 'test dir'
mkdir '\dir with\ backslashes\\\'
touch '\file with \\backslashes\'
touch 'An-Beat - Mentally Insine (Original Mix).mp3'
mkdir 'crazy(*@$):{}[]dir:'
mkdir 'dir with 字 chinese 鳥鸟 characters'
touch $'file\twith\tmany\ttabs.txt'
touch 'file @*&$()!#[]:.txt'
touch 'file
with
newlines.txt'
Executing escpaths
in the test directory test dir
gives the escaped output:
$'/.../test dir/file\nwith\nnewlines.txt'
$'/.../test dir/file\twith\tmany\ttabs.txt'
/.../test\ dir
/.../test\ dir/An-Beat\ -\ Mentally\ Insine\ \(Original\ Mix\).mp3
/.../test\ dir/\\dir\ \ with\\\ backslashes\\\\\\
/.../test\ dir/\\file\ with\ \\\\backslashes\\
/.../test\ dir/crazy\(\*@\$\):\{\}\[\]dir:
/.../test\ dir/dir\ with\ 字\ chinese\ 鳥鸟\ characters
/.../test\ dir/file\ @\*\&\$\(\)\!#\[\]:.txt
Solution to get escaped basenames only
This (also portable) function will get you the escaped basenames of all items in the current directory (this time excluding the current directory).
escbasenames() {
find . -mindepth 1 -maxdepth 1 -exec printf '%s\0' "$(basename {})" \; | xargs -0 -I {} bash -c 'printf "%q\n" "${0#./}"' {} | sort
}
Running escbasenames
in the same test directory test dir
gives the escaped basenames:
$'file\nwith\nnewlines.txt'
$'file\twith\tmany\ttabs.txt'
An-Beat\ -\ Mentally\ Insine\ \(Original\ Mix\).mp3
\\dir\ \ with\\\ backslashes\\\\\\
\\file\ with\ \\\\backslashes\\
crazy\(\*@\$\):\{\}\[\]dir:
dir\ with\ 字\ chinese\ 鳥鸟\ characters
file\ @\*\&\$\(\)\!#\[\]:.txt
Final notes
Note that if the path/filename contains newlines or tabs, it will be encoded as an ANSI-C string. Autocompletion in the terminal also completes with ANSI-C strings. Example ANSI-C string autocompletion outputs would look like my$'\n'newline$'\n'dir/
or my$'\t'tabbed$'\t'file.txt
.