Issue
I am trying to store the output of this:
mdfind "kMDItemContentType == 'com.apple.application-bundle'"
/Applications/Safari.app
/Applications/Xcode.app
/Applications/Xcode.app/Contents/Applications/Accessibility Inspector.app
/Applications/Xcode.app/Contents/Applications/RealityComposer.app
/Applications/Xcode.app/Contents/Applications/FileMerge.app
/Applications/Xcode.app/Contents/Applications/Instruments.app
/Applications/Xcode.app/Contents/Applications/Create ML.app
I try to store it as an array but the contents are split per spaces:
bash-5.1$ arr=( $(/usr/bin/mdfind "kMDItemContentType == 'com.apple.application-bundle'") )
bash-5.1$ echo ${arr[2]}
/Applications/Xcode.app/Contents/Applications/Accessibility
bash-5.1$ echo ${arr[3]}
Inspector.app
bash-5.1$
So how can I do the trick?
Solution
Use readarray
and process substitution to read a null-delimited series of paths into an array.
readarray -d '' arr < <(mdfind -0 "...")
The -0
option tells mdfind
to terminate each path with a null byte instead of a linefeed. (This guards agains rare, but legal, path names that include linefeeds. Null bytes are not a valid character for any path component.)
The -d ''
option tells readarray
to treat the null byte as the end of a "line".
readarray
populates an array with one "line" of input per element. The input is the output of mdfind
; the process substitution ensures that readarray
executes in the current shell, not a subshell induced by a pipe like
mdfind -0 "..." | readarray -d '' arr
(Under some situations, you can make the last job of a pipeline execute in the current shell; that's beyond the scope of this answer, though.)
Example:
# Using printf to simulate mdfind -0
$ readarray -d '' arr < <(printf 'foo\nbar\000baz\000')
$ declare -p arr
declare -a arr=([0]=$'foo\nbar' [1]="baz")
Answered By - chepner Answer Checked By - Cary Denson (WPSolving Admin)