You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何过滤传给xargs的文件中带shebang的Swift文件

核心诉求

我尝试编写一个简单脚本,编译指定文件夹及其所有子文件夹内的所有.swift文件,但需要排除所有开头带shebang的文件。

详细说明

我计划开发一个简易工具,无需依赖高级IDE或项目配置文件,即可将多个Swift文件编译为单个输出产物。项目以找到main.swift文件的位置为根目录,目录结构本身即为项目的定义依据。

假设我已经定位到main.swift并进入对应目录,首先使用find命令查找所有相关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"

注意:由于find命令使用了-print0参数,xargs侧使用-0参数匹配,所有n个参数会一次性传给单次执行的xcrun,而非分n次执行xcrun每次传1个参数,整个过程仅执行一次编译,生成单个输出文件。

目前遇到的问题是:如果查找到的Swift文件是Swift脚本文件(即开头带shebang的文件),编译器会拒绝编译。这类文件通常还包含顶层语句,除非是main.swift,否则编译器同样不支持该写法。

举例来说,如果名为someutil的文件内容如下:

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

执行chmod +x someutil为文件添加可执行权限后,只要该文件在PATH路径下,就可以像其他Shell脚本一样直接执行:

echo Here we go!
someutil
echo Done!

执行输出为:

Here we go!
Hello from Swift
Done!

但如果将该文件传给编译器,编译器会同时抛出两类错误:一是文件包含shebang,二是非main.swift文件包含顶层语句。

因此我需要过滤掉所有开头带shebang的文件,将该特征作为需要排除的Swift脚本的识别标识。

我目前查到的grep教程大多只说明如何筛选包含指定内容的文件,没有找到排除这类文件的方案,尤其现有代码逻辑依赖find命令的-print0参数,无法很方便地在其他环节做过滤。

更新:使用ArgChecker工具验证参数

目前收到的部分回答看似可行,但实际无法正确处理参数。为验证方案正确性,我推荐先编写如下名为'argchecker'的工具:创建包含以下内容的文件,执行chmod +x添加可执行权限后加入系统PATH路径。测试时将你认为可行的方案中原本传给xcrun编译器的内容替换为传给argchecker即可,很多错误方案最终不会传入n个独立参数,而是将所有参数拼接为单个参数传入。

'argchecker'文件内容

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

之后执行如下命令:

chmod +x argchecker

将其加入PATH路径后,在添加过滤逻辑的位置使用如下命令测试脚本即可:

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

可行方案

全程保留null分隔符传递逻辑,不会破坏参数结构,可直接通过argchecker验证,提供两种实现方式:

方案1:纯find内置逻辑实现(兼容性最好)

不需要依赖grep的特殊参数,直接在find遍历阶段完成过滤:

find * -type f -name "*.swift" -exec sh -c '
  for file do
    IFS= read -r first_line < "$file"
    case "$first_line" in
      "#!"*) continue ;;
      *) printf "%s\0" "$file" ;;
    esac
  done
' sh {} + | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"
  • 全程使用null字符分隔文件名,所有文件会作为独立参数传入编译器,不会出现参数拼接错误
  • 仅读取每个文件的第一行做判断,性能开销极低
  • 自动兼容带空格、特殊字符、甚至换行符的异常文件名
  • 无额外依赖,macOS系统自带工具即可直接运行

方案2:grep简洁实现(代码更短)

利用grep的反向匹配参数实现过滤,代码更精简:

find * -type f -name "*.swift" -print0 | xargs -0 grep -L -m1 "^#!" -Z | xargs -0 xcrun -sdk macosx swiftc -o "$OUTPUT_FILE"

参数说明:

  • -m1:匹配到第一行就停止读取文件,不需要遍历整个文件内容
  • -L:输出不包含匹配规则的文件名,刚好实现排除shebang文件的需求
  • -Z:输出文件名时使用null字符分隔,和前后的-print0、xargs -0逻辑完全兼容,不会破坏参数传递

内容的提问来源于stack exchange,提问作者Mark A. Donohoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:51:22