如何用传递给Xargs的Shebang过滤文件?

发布于 2025-02-13 20:12:12 字数 2637 浏览 3 评论 0原文

TL; DR

我正在尝试编写一个简单的脚本,该脚本在给定文件夹和任何一个子文件夹中编译所有.swift文件,但它不包括以Shebang开头的那些文件。

我正在尝试编写一个简单的实用程序的详细信息

,该实用程序将使我将多个Swift文件编译为单个编译的输出,而无需任何高级IDE或项目文件等。文件夹结构本身将是项目的定义,而root在i的位置i。查找main.swift文件。

假设我已经找到了main.swift and Am在ever Directory中,从查找命令开始,我可以找到所有相关的swift文件,例如

find * -type f -name "*.swift"

...另一个答案在这里,通过附加-print0,并将其馈送给XARGS -0,它们都可以一口气发送到Swift编译器,就像这样...

find * -type f -name "*.swift" -print0 | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

注意:多亏了-print0上找到命令和xargs -0在另一侧,所有 n 参数同时以 同时传递给一个执行xcrun的执行的xcrun每个参数。只有一个汇编和一个输出文件。

问题是,如果将这些Swift文件中的任何一个设置为Swift脚本文件(即以Shebang开头的文件),则编译器会拒绝它们。它们也很可能包含顶级语句,除非它们在main.swift中,否则编译器也不喜欢。

例如,如果这是在文件someutil ...

#! /usr/bin/env swift
print("Hello from Swift!")

...并且您ran chmod +x someutil中,您现在可以像任何其他任何其他shell script一样执行swift文件只要它可以在路径中到达。

echo Here we go!
someutil
echo Done!

但是

Here we go!
Hello from Swift
Done!

,如果您将该文件发送到编译器,它将抱怨Shebang和关于不在main.swift的顶级语句。

因此,我试图过滤掉以Shebang开头的任何发现的文件,基本上将其用作Swift脚本的标识符,以排除在外。

我已经看到了很多关于如何仅包括这些文件的GREP教程,但找不到任何排除它们,尤其是因为上述代码也取决于-print0 find命令本身(这意味着我无法轻易在其他地方进行过滤。)

所以这是可能的吗?

更新 - 使用Argchecker util验证。

这里的几个答案出现是正确的,但实际上并未正确处理参数。要检查这一点,我建议创建以下“ Argchecker”实用程序。只需创建一个带有以下内容的文件,在其上运行chmod +x,然后将其添加到您的路径中。现在,您认为您认为有效的任何解决方案输出到argchecker而不是xcrun编译器行。在其中很多情况下,您会看到而不是“ n”参数,您将获得一个与所有预期的论点相连的参数。

文件'argchecker'

#! /usr/bin/env bash
echo "There are $# arguments:"
for ((i=1; i<=$#; i++))
do
    echo " $i: ${!i}"
done

然后运行此...

chmod +x argchecker

并将其放在您的路径中。最后,在任何地方添加过滤器测试您的脚本。

find * -type f -name "*.swift" -print0 | xargs -0 argchecker

TL;DR

I'm trying to write a simple script that compiles all .swift files in a given folder and any of it's subfolders, but which excludes those files that start with a shebang.

The Details

I'm trying to write a simple utility that will let me compile multiple Swift files into a single compiled output without requiring any advanced IDEs or project files, etc. The folder structure itself will be the project's definition with the root being wherever I find a main.swift file.

Assuming I've already found main.swift and am in the according directory, starting with the find command, I can find all relevant Swift files like so...

find * -type f -name "*.swift"

Thanks to another answer here, by appending -print0 and feeding that to xargs -0, they can all be sent to swift compiler in one fell swoop, like so...

find * -type f -name "*.swift" -print0 | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

Note: thanks to the use of -print0 on the find command and xargs -0 on the other side, all n arguments are passed in at the same time to one execution of xcrun, not n executions of xcrun with one argument each. There is only one compilation and one single output file.

The issue is if any of those Swift files are set up as Swift script files (i.e. those that start with a shebang), the compiler rejects them. They're also most likely to contain top-level statements, something the compiler also doesn't like unless they are in main.swift.

For instance, if this is in the file someutil...

#! /usr/bin/env swift
print("Hello from Swift!")

...and you ran chmod +x someutil, you could now execute that Swift file like any other shell script so long as it's reachable in the path.

echo Here we go!
someutil
echo Done!

Output

Here we go!
Hello from Swift
Done!

However, if you send that file to the compiler, it will complain both about the shebang and about the top-level statements not being in main.swift.

As such, I'm trying to filter out any of the found files which start with a shebang, using that basically as the identifier of Swift scripts to be excluded.

I've seen a lot of grep tutorials for how to include only those files, but can't find any that exclude them, especially since the above code also depends on the -print0 of the find command itself (meaning I can't easily do the filtering elsewhere.)

So is this possible?

Update - Verify with ArgChecker util.

Several of the answers here appear to be correct, but don't actually process the arguments correctly. To check this, I recommend creating the following 'argchecker' utility. Simply create a file with the following contents, run chmod +x on it and add it to your path. Now make whatever solution you think works output to argchecker instead of the xcrun compiler line. In a lot of these you will see instead of 'n' arguments, you get a single argument with all the expected ones concatenated together.

File 'argchecker'

#! /usr/bin/env bash
echo "There are $# arguments:"
for ((i=1; i<=$#; i++))
do
    echo " $i: ${!i}"
done

Then run this...

chmod +x argchecker

and put it in your path. Finally, test your script like this with the filtering added wherever.

find * -type f -name "*.swift" -print0 | xargs -0 argchecker

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

葬﹪忆之殇 2025-02-20 20:12:13

您可以使用的输出来运行一个循环,查找命令并运行grep内部:

while IFS= read -rd '' f; do
   grep -qF '#! /usr/bin/env swift' "$f" || printf '%s\0' "$f"
done < <(find . -type f -name "*.swift" -print0) |
xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

详细信息:

  • 查找。 -type f -name“*.swift” -print0:查找*。swift文件,并使用nul terminator
  • &lt; &lt;(...)是过程替换
  • 而ifs = read -rd''f:从nul终止数据中读取输入。 ps:ifs =-d''都是
  • || printf'%s \ 0'“ $ f”仅在grep命令失败时,才打印出具有NUL终端的文件名。
  • | XARGS -0 XCRUN -SDK MACOSX SWIFTC -O“ $ output_file” make xcrun命令在最终输出时仅一次命令

You can run a loop with output of find command and run a grep inside:

while IFS= read -rd '' f; do
   grep -qF '#! /usr/bin/env swift' "$f" || printf '%s\0' "$f"
done < <(find . -type f -name "*.swift" -print0) |
xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

Details:

  • find . -type f -name "*.swift" -print0: finds *.swift files and prints them with a NUL terminator
  • < <(...) is process substitution
  • while IFS= read -rd '' f: Make while loop read input from NUL terminated data. PS: both IFS= and -d '' are required
  • || printf '%s\0' "$f" prints file names with NUL terminator only when grep command fails.
  • | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE" makes xcrun command only once on final output of while loop
深爱成瘾 2025-02-20 20:12:13

您也许可以进行优化。我假设像任何普通的UNIX一样,脚本具有可执行的权限,在这种情况下,您可以执行

find * -name '*.swift' ! -perm -u+x -print0 | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

此操作。 > -perm- )用户使用execute(u+x)。

You may be able to make an optimization. I'm assuming like any normal Unix, scripts have executable permissions, in which case you could do

find * -name '*.swift' ! -perm -u+x -print0 | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

This means match any file that does not (!) have permissions (-perm -) of user with execute (u+x).

肤浅与狂妄 2025-02-20 20:12:13

可以使用grep <代码>查找和xcrun

find * -type f -name "*.swift" -print0 | xargs -0 grep -L '^#! /usr/bin/env swift

grep 选项:

  • -l <​​/code >:抑制正常输出;取而代之的是打印每个输入文件的名称,通常不会从中打印任何输出
  • -z :输出一个零字节(assii nul carnem),而不是通常遵循文件名的字符。

说明:

第一步

find * -type f -name "*.swift" -print0

返回所有被NUL字符分开的发现的文件。请参阅:

find * -type f -name "*.swift" -print0 | cat -v

输出:

ex1.swift^@ex2.swift^@ex3.swift^@

^@是漂亮的印刷nul chars

第二步

... | xargs -0 grep -L '^#! /usr/bin/env swift

xargs 谁接受Nul Char的分离元素( -0) 选项),在每个元素上启动 grep 命令。
grep 仅返回文件( -l <​​/code>或 -l <​​/code>选项),他们不包含令牌( -L 选项)并通过nul char分开每个结果( -z 选项)。查看他们:

find * -type f -name "*.swift" -print0 | xargs -0 grep -L '^#! /usr/bin/env swift

输出:

ex1.swift^@ex3.swift^@

警告:

  • 检查re ^#! /usr/bin/env Swift $ 如果完全按照您的需求;
  • 如果使用BSD GREP 命令在MacOS上运行,请检查 -L -Z 选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行 xcrun 命令

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep 选项:

  • -l <​​/code >:抑制正常输出;取而代之的是打印每个输入文件的名称,通常不会从中打印任何输出
  • -z :输出一个零字节(assii nul carnem),而不是通常遵循文件名的字符。

说明:

第一步


返回所有被NUL字符分开的发现的文件。请参阅:


输出:


^@是漂亮的印刷nul chars

第二步


xargs 谁接受Nul Char的分离元素( -0) 选项),在每个元素上启动 grep 命令。
grep 仅返回文件( -l <​​/code>或 -l <​​/code>选项),他们不包含令牌( -L 选项)并通过nul char分开每个结果( -z 选项)。查看他们:


输出:


警告:

  • 检查re ^#! /usr/bin/env Swift $ 如果完全按照您的需求;
  • 如果使用BSD GREP 命令在MacOS上运行,请检查 -L -Z 选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行 xcrun 命令

-Z

xargs 谁接受Nul Char的分离元素( -0) 选项),在每个元素上启动 grep 命令。
grep 仅返回文件( -l <​​/code>或 -l <​​/code>选项),他们不包含令牌( -L 选项)并通过nul char分开每个结果( -z 选项)。查看他们:


输出:


警告:

  • 检查re ^#! /usr/bin/env Swift $ 如果完全按照您的需求;
  • 如果使用BSD GREP 命令在MacOS上运行,请检查 -L -Z 选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行 xcrun 命令

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep选项:

  • -l <​​/code >:抑制正常输出;取而代之的是打印每个输入文件的名称,通常不会从中打印任何输出
  • -z:输出一个零字节(assii nul carnem),而不是通常遵循文件名的字符。

说明:

第一步

返回所有被NUL字符分开的发现的文件。请参阅:

输出:

^@是漂亮的印刷nul chars

第二步

xargs谁接受Nul Char的分离元素(-0)选项),在每个元素上启动grep命令。
grep仅返回文件(-l <​​/code>或-l <​​/code>选项),他们不包含令牌(-L选项)并通过nul char分开每个结果(-z选项)。查看他们:

输出:

警告:

  • 检查re ^#! /usr/bin/env Swift $如果完全按照您的需求;
  • 如果使用BSD GREP命令在MacOS上运行,请检查-L-Z选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行xcrun命令

-Z | cat -v

输出:

警告:

  • 检查re ^#! /usr/bin/env Swift $如果完全按照您的需求;
  • 如果使用BSD GREP命令在MacOS上运行,请检查-L-Z选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行xcrun命令

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep选项:

  • -l <​​/code >:抑制正常输出;取而代之的是打印每个输入文件的名称,通常不会从中打印任何输出
  • -z:输出一个零字节(assii nul carnem),而不是通常遵循文件名的字符。

说明:

第一步

返回所有被NUL字符分开的发现的文件。请参阅:

输出:

^@是漂亮的印刷nul chars

第二步

xargs谁接受Nul Char的分离元素(-0)选项),在每个元素上启动grep命令。
grep仅返回文件(-l <​​/code>或-l <​​/code>选项),他们不包含令牌(-L选项)并通过nul char分开每个结果(-z选项)。查看他们:

输出:

警告:

  • 检查re ^#! /usr/bin/env Swift $如果完全按照您的需求;
  • 如果使用BSD GREP命令在MacOS上运行,请检查-L-Z选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行xcrun命令

-Z

xargs谁接受Nul Char的分离元素(-0)选项),在每个元素上启动grep命令。
grep仅返回文件(-l <​​/code>或-l <​​/code>选项),他们不包含令牌(-L选项)并通过nul char分开每个结果(-z选项)。查看他们:

输出:

警告:

  • 检查re ^#! /usr/bin/env Swift $如果完全按照您的需求;
  • 如果使用BSD GREP命令在MacOS上运行,请检查-L-Z选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行xcrun命令

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep选项:

  • -l <​​/code >:抑制正常输出;取而代之的是打印每个输入文件的名称,通常不会从中打印任何输出
  • -z:输出一个零字节(assii nul carnem),而不是通常遵循文件名的字符。

说明:

第一步

返回所有被NUL字符分开的发现的文件。请参阅:

输出:

^@是漂亮的印刷nul chars

第二步

xargs谁接受Nul Char的分离元素(-0)选项),在每个元素上启动grep命令。
grep仅返回文件(-l <​​/code>或-l <​​/code>选项),他们不包含令牌(-L选项)并通过nul char分开每个结果(-z选项)。查看他们:

输出:

警告:

  • 检查re ^#! /usr/bin/env Swift $如果完全按照您的需求;
  • 如果使用BSD GREP命令在MacOS上运行,请检查-L-Z选项与GNU GREP 在Linux或其他系统下。

第三步
与第二步相同,除了执行xcrun命令

May be with a grep command between find and xcrun:

find * -type f -name "*.swift" -print0 | xargs -0 grep -L '^#! /usr/bin/env swift

grep option:

  • -L: Suppress normal output; instead print the name of each input file from which no output would normally have been printed
  • -Z: Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.

Explanations:

1st step

find * -type f -name "*.swift" -print0

Return all found files separated by NUL character. See them with:

find * -type f -name "*.swift" -print0 | cat -v

Output:

ex1.swift^@ex2.swift^@ex3.swift^@

^@ are pretty printed NUL chars

2nd step

... | xargs -0 grep -L '^#! /usr/bin/env swift

xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:

find * -type f -name "*.swift" -print0 | xargs -0 grep -L '^#! /usr/bin/env swift

Output:

ex1.swift^@ex3.swift^@

Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep option:

  • -L: Suppress normal output; instead print the name of each input file from which no output would normally have been printed
  • -Z: Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.

Explanations:

1st step


Return all found files separated by NUL character. See them with:


Output:


^@ are pretty printed NUL chars

2nd step


xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:


Output:


Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z

xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:


Output:


Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep option:

  • -L: Suppress normal output; instead print the name of each input file from which no output would normally have been printed
  • -Z: Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.

Explanations:

1st step

Return all found files separated by NUL character. See them with:

Output:

^@ are pretty printed NUL chars

2nd step

xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:

Output:

Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z | cat -v

Output:

Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep option:

  • -L: Suppress normal output; instead print the name of each input file from which no output would normally have been printed
  • -Z: Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.

Explanations:

1st step

Return all found files separated by NUL character. See them with:

Output:

^@ are pretty printed NUL chars

2nd step

xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:

Output:

Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z

xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:

Output:

Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

-Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

grep option:

  • -L: Suppress normal output; instead print the name of each input file from which no output would normally have been printed
  • -Z: Output a zero byte (the ASCII NUL character) instead of the character that normally follows a file name.

Explanations:

1st step

Return all found files separated by NUL character. See them with:

Output:

^@ are pretty printed NUL chars

2nd step

xargs who accept separated elements by NUL char (-0 option), launch grep command on each element.
grep returns file only (-l or -L option) who DO NOT contains token (-L option) and separate each results by NUL char (-Z option). See them with:

Output:

Warning:

  • Check the RE ^#! /usr/bin/env swift$ if exactly as you want;
  • If you run on macos with BSD grep command, check if -L and -Z options are same as GNU grep under Linux or other systems.

3rd step
Same as 2nd step except to execute xcrun command

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文