user3680708
user3680708

Reputation: 117

problems with source command in shell

Good afternoon I have the following command to run me 'code.sh' file which I pass a parameter '$ 1' the problem is that I want to run a 'code.sh' with 'source' this is my command:

find . -name "*.txt" -type f -exec ./code.sh {} \;

And I do do well occupied

source ./code.sh

Upvotes: 2

Views: 240

Answers (2)

John Kugelman
John Kugelman

Reputation: 362137

This is tricky. When you source a script you need to do it in the current shell, not in a sub-shell or child process. Executing source from find won't work because find is a child process, and so changes to environment variables will be lost.

It's rather roundabout, but you can use a loop to parse find's output and run the source commands directly in the top-level shell (using process substitution).

while read -d $'\0' fileName; do
    source code.sh "$fileName"
done < <(find . -name "*.txt" -type f -print0)

Now what's with -print0 and -d $'\0', you ask? Using these two flags together is a way of making the script extra safe. File names in UNIX are allowed to contain lots of oddball characters including spaces, tabs, and even newlines. While newlines are rare, they are indeed legal.

-print0 tells find to use NUL characters (\0) to separate the file names rather than the default newlines (\n). Doing this means file names containing \n won't mess up the loop. Using \0 as a separator works well because \0 is not a legal character in file names.

-d $'\0' does the same thing with read on the other side. It tells read that lines are delimited with \0 instead of \n.


You may have seen this trick before. It's common to write find ... -print0 | xargs -0 ... to get the same sort of safety when pairing find with xargs.

If you're wondering about $'...': that's Bash ANSI-C quoting syntax for writing string literals containing escape codes. Dollar sign plus single quotes. You can write $'\n' for a newline or $'\t' for a tab or $'\0' for a NUL.

Upvotes: 3

chepner
chepner

Reputation: 532398

You won't be able to use find in this way; it will always execute a command in a separate process, not the current shell. If you are using bash 4, there's a simple alternative to using find:

shopt -s globstar
for f in **/*.txt; do
    [[ -f $f ]] && source code.sh "$f"
done

Upvotes: 2

Related Questions