Skip to main content
added 179 characters in body
Source Link
Stéphane Chazelas
  • 586.4k
  • 96
  • 1.1k
  • 1.7k

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

You might also use zsh-style recursive globbing with with globstar option in bash 4.0 and later:

shopt -s globstar failglob dotglob
(. myscript ./**/something.txt)

Note that ** followed symlinks to directories until it was fixed in bash 4.3. Also note that bash doesn't implement zsh globbing qualifiers so you won't get all the features of find there.

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

You might also use globstar in bash 4.0 and later:

shopt -s globstar failglob dotglob
(. myscript ./**/something.txt)

Note that ** followed symlinks to directories until bash 4.3.

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

You might also use zsh-style recursive globbing with with globstar option in bash 4.0 and later:

shopt -s globstar failglob dotglob
(. myscript ./**/something.txt)

Note that ** followed symlinks to directories until it was fixed in bash 4.3. Also note that bash doesn't implement zsh globbing qualifiers so you won't get all the features of find there.

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

globstar is not enabled by default, the extra -s resulted in an error, and ** doesn't follow symlinks to directories in bash 4.3
Source Link

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

If you know that there is no symlink to directories in there, you couldYou might also use zshglobstar style recursive globbingin (bash improperly copied zsh's **/ as it follows the symlinks when descending the directory tree)4.0 and later:

shopt -s failglobglobstar -sfailglob dotglob
(. myscript ./**/something.txt)

(that's quite limited as in bash, you wouldn't have the equivalent of find's Note that -type f** and other non-named basedfollowed symlinks to directories until findbash predicates)4.3.

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

If you know that there is no symlink to directories in there, you could use zsh style recursive globbing (bash improperly copied zsh's **/ as it follows the symlinks when descending the directory tree):

shopt -s failglob -s dotglob
(. myscript ./**/something.txt)

(that's quite limited as in bash, you wouldn't have the equivalent of find's -type f and other non-named based find predicates).

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

You might also use globstar in bash 4.0 and later:

shopt -s globstar failglob dotglob
(. myscript ./**/something.txt)

Note that ** followed symlinks to directories until bash 4.3.

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

typo
Source Link
Stéphane Chazelas
  • 586.4k
  • 96
  • 1.1k
  • 1.7k

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

If you know that there is no symlink to directories in there, you could use zsh style recursive globbing (bash improperly copied zsh's **/ as it follows the symlinks when descending the directory tree):

shopt -s failglob -s dotglob
(. myscript ./**/something.txt)

(that's quite limited as in bash, you wouldn't have the equivalent of find's -type f and other non-named based find predicates).

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always) {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

If you know that there is no symlink to directories in there, you could use zsh style recursive globbing (bash improperly copied zsh's **/ as it follows the symlinks when descending the directory tree):

shopt -s failglob -s dotglob
(. myscript ./**/something.txt)

(that's quite limited as in bash, you wouldn't have the equivalent of find's -type f and other non-named based find predicates).

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always) {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

A few addition to @slm's fine answer.

The limitation on the size of the arguments is on the execve(2) system call (actually, it's on the cumulative size of the argument and environment strings and pointers). If myscript is written in a language that your shell can interpret, then maybe you don't need to execute it, you could have your shell just interpret it without having to execute another interpreter.

If you run the script as:

(. myscript x y)

It's like:

myscript x y

Except that it's being interpreted by a child of the current shell, instead of executing it (which eventually involves executing sh (or whatever the she-bang line specifies if any) with even more arguments).

Now obviously, you can't use find -exec {} + with the . command, as . being a builtin command of the shell, it has to be executed by the shell, not by find.

With zsh, it's easy:

IFS=$'\0'
(. myscript $(find ... -print0))

Or:

(. myscript ${(ps:\0:)"$(find ... -print0)"}

Though with zsh, you wouldn't need find in the first place as most of its features are built into zsh globbing.

bash variables however cannot contain NUL characters, so you have to find another way. One way could be:

files=()
while IFS= read -rd '' -u3 file; do
  files+=("$file")
done 3< <(find ... -print0)
(. myscript "${files[@]}")

If you know that there is no symlink to directories in there, you could use zsh style recursive globbing (bash improperly copied zsh's **/ as it follows the symlinks when descending the directory tree):

shopt -s failglob -s dotglob
(. myscript ./**/something.txt)

(that's quite limited as in bash, you wouldn't have the equivalent of find's -type f and other non-named based find predicates).

Another alternative would be to use GNU ls:

eval "files=(find ... -exec ls -d --quoting-style=shell-always {} +)"
(. myscript "${files[@]}")

The above methods can also be used if you want to make sure myscript is executed only once (failing if the argument list is too large). On recent versions of Linux, you can raise and even lift that limitation on the argument list with:

ulimit -s 1048576

(1GiB stack size, a quarter of which can be used for the arg+env list).

ulimit -s unlimited

(no limit)

Source Link
Stéphane Chazelas
  • 586.4k
  • 96
  • 1.1k
  • 1.7k
Loading