Akif
Akif

Reputation: 6786

How to get variables from subshell while also passing arguments with xargs?

I would like to pass filename to xargs and process it in subshell, then get the certain variables from subshell to the current shell. I prefer xargs here for parallelizing purposes.

Here is a sample code:

files_with_issues=()
printf "%s\n" ${list_of_file_names[@]} | xargs -n1 -P4 -I {file} bash -c '
        # Process the file ...
        exit_status=$?
        [ ${exit_status} -ne 0 ] && files_with_issues+=({file})'

echo "${files_with_issues[@]}"

I am considering to use something like source or . to get variables from subshells. However I could not figure out how to achieve this?

Upvotes: 0

Views: 814

Answers (2)

Akif
Akif

Reputation: 6786

It seems that only way is to write the variable into a file and then capture it from the main shell. Here is how I handle it:

capture="capture.log"
text_to_capture="file_with_an_issue: "
[ -e ${capture} ] && rm ${capture}     #(1)
printf "%s\n" ${list_of_file_names[@]} | xargs -n1 -P4 -I {file} bash -c '
    # Process the file ...
    exit_status=$?
    [ ${exit_status} -ne 0 ] && echo "${text_to_capture}{file}" >> ${capture}'     #(2)

files_with_issues=$(grep -oP "(?<=${text_to_capture}).*" ${capture})     #(3)

Some notes:

1) [ -e ${capture} ] && rm ${capture}

Ensure the file is not existed, before appending any text.

2) echo "${text_to_capture}{file}" >> ${capture}

Append certain text and variable to the file by >> and list up all.

3) grep -oP "(?<=text_to_capture).*" ${capture}

Capture the variable from the file by the help of grep and regex

Upvotes: 0

l0b0
l0b0

Reputation: 58788

Answer to new question

If you need to do complex things with each file you'll want to pass it either as standard input or parameters to a script. The script can then output NUL-separated filenames which you can then capture in an array:

while IFS= read -r -d '' -u 9 file
do
    files_with_issues+=("$file")
done 9< <(./process_files.sh <<< "${list_of_file_names[@]}")

Answer to original question

Since

$ echo foo | xargs -I {file} bash -c 'echo "Information about {file}"'
Information about foo

you can do

$ info="$(echo foo | xargs -I {file} bash -c 'echo "Information about {file}"')"

Upvotes: 1

Related Questions