介绍
OPEN CIRCLE 正在筹备一个社区艺术下午。欢迎工具包显示完整节目,包括 Chloé Martín、林雨、佐藤葵 和 João Silva。正常样例可以运行,新导出的副本却不能。
你将修复独立交付副本并保留原件。仅需基本终端操作经验;课内会说明权限、脚本首行和字符编码为何是不同问题。读取程序已经准备好,无需编写 Python 或通用转换器。
全程使用浏览器中的 Terminal。所有译文都保留样例数据和终端输出的原始语言。
修复启动入口并保留原件
本步骤将比较正常工具包和导出文件,制作可直接执行的交付入口。使用 Terminal。
先读取真实结果
cd 更改当前工作目录。./ 表示执行相对于该目录的文件;路径中的斜杠让 shell 使用指定路径,而不是搜索命令名称。先运行提供的正常样例:
cd /home/labex/project/event
./sample/start.sh
OPEN CIRCLE | Afternoon
14:00 — Welcome / Chloé Martín
14:30 — 纸艺工坊 / 林雨
15:15 — 音の庭 / 佐藤葵
16:00 — Café & questions / João Silva
逐行读取,包括空白分隔行。这是提供的读取程序实际解码的文字,不是截图或成功标签。cat 输出文件文字。选择转换方式前先读导出说明:
cat source/export-receipt.txt
说明声明 start.sh 为采用 CRLF 行尾的 UTF-8,programme.txt 为带 BOM 的 UTF-16-LE。其他文件已经是采用 LF 行尾的 UTF-8。扩展名不能确定编码。
区分权限和解释器入口
ls -l 显示权限;x 表示执行权限。脚本首行称为 shebang,以 #! 开头并指定解释器。直接执行既需要有效的解释器入口,也需要执行权限。尝试导出的启动脚本;此处预期失败:
ls -l source/start.sh
./source/start.sh
预期出现 permission denied。修改文字不能授予权限。bash file 则让 Bash 读取文件,绕过直接执行及其 shebang。这个特定脚本在命令后有注释,末尾的 CR 因此位于注释内。试试看:
bash source/start.sh
预期出现 Cannot read programme.txt 和 UTF-8 解码错误。这是另一类失败:读取程序已运行,但无法解码数据。显式调用 Bash 在这里提供了调查证据,不能证明直接执行已就绪。
cp -a 复制目录内容并保留文件权限模式。/. 表示目录内容,包括隐藏文件。制作交付副本,保持 source/ 和 sample/ 不变。mkdir -p 创建目录及缺失的父目录;目录已经存在时也会成功。chmod u+x 给文件所有者(u)添加执行权限,不改变其他权限:
mkdir -p delivery
cp -a source/. delivery/
chmod u+x delivery/start.sh
./delivery/start.sh
直接执行仍然失败,解释器错误可能是 bad interpreter: /bin/bash^M: no such file or directory。有些 shell 会显示 cannot execute: required file not found。脚本确实存在;问题是解释器路径末尾的 CR 字节。不要继续重复 chmod。
观察字节,只修正脚本行尾
LF 是字节 0a;CRLF 是 0d 0a。file 根据字节特征提供格式描述。od -An -tx1 -N16 以十六进制输出前 16 字节,省略地址标签。结合来源说明和字节判断;file 并非绝对准确的编码检测器:
file source/start.sh source/programme.txt
od -An -tx1 -N16 source/start.sh
shebang 以 0d 0a 结束。行尾和字符编码是不同属性:脚本本来就是 UTF-8。Linux 应用可以读取 CRLF 文本;这里失败的是直接执行脚本时的解释器路径。
sed 's/\r$//' 只删除行末的 CR。单引号保留表达式;$ 表示行尾。> 将标准输出写入另一个文件,重试时覆盖它。绝不能重定向到输入文件:shell 会在 sed 读取前清空输入。&& 仅在前一命令成功后执行下一条。mv 再重命名完整的临时文件:
sed 's/\r$//' source/start.sh > delivery/start.tmp && mv delivery/start.tmp delivery/start.sh
chmod u+x delivery/start.sh
od -An -tx1 -N16 delivery/start.sh
./delivery/start.sh
shebang 现在以 0a 结束。最后一条命令到达 Cannot read programme.txt,与显式 Bash 调用相同。这表示已经到达数据边界,不代表整个工具包完成。若操作有误,从 source/start.sh 重新转换并恢复执行权限;不要修改原件。
转换节目文字并使用独立交付
本步骤将解码已声明的 UTF-16 来源,保留全部节目文字,并从其他目录运行交付。继续在 Terminal 中操作,当前目录为 /home/labex/project/event。
使用源编码证据
字符编码将字符映射为字节。UTF-8 和 UTF-16 可以用不同字节表示相同姓名。UTF-16 文件开头的 BOM(字节顺序标记)记录字节序:ff fe 表示小端,fe ff 表示大端,两者都属于 UTF-16。这里 BOM 是有用证据,并非普遍有害的前缀。
od -An -tx1 -N16 source/programme.txt
开头的 ff fe 与说明中的 UTF-16-LE 一致。读取程序的公开输入要求是无 BOM 的 UTF-8。它接受文本数据中的 CRLF,但无法把这些 UTF-16 字节按 UTF-8 解码。删除 CR 字节或修改扩展名不能完成解码。
iconv -f UTF-16 -t UTF-8 解码带 BOM 的 UTF-16 输入,再编码为 UTF-8。-f 指定源格式,-t 指定目标格式;UTF-16 利用 BOM 选择字节序。先保存到临时目标,成功后才提升为正式文件:
iconv -f UTF-16 -t UTF-8 source/programme.txt > delivery/programme.tmp && mv delivery/programme.tmp delivery/programme.txt
file delivery/programme.txt
od -An -tx1 -N16 delivery/programme.txt
cat delivery/programme.txt
开头现在是标题的 UTF-8 字节,不是 ff fe、fe ff 或 UTF-8 BOM ef bb bf。对照样例检查每个人名:删除非 ASCII 字符即使使文件可解码,也会丢失活动内容。
如果 iconv 报错,输出可能不完整。&& 可以防止这个不完整文件成为正式文件。核对声明的源编码,从未修改的源文件重试;不要使用 -c 或 //IGNORE 静默丢弃字符。本课处理完整且编码已声明的文件,不涉及猜测或修复损坏的导出内容。
保留已经正常的文件
about.sh 和 door-sign.txt 原本正确,无需转换。cmp 比较字节;文件相同则不输出文字并返回成功。下面两次比较都应没有输出:
cmp source/about.sh delivery/about.sh
cmp source/door-sign.txt delivery/door-sign.txt
./delivery/about.sh
cat delivery/door-sign.txt
预期看到社区艺术简介以及 Bienvenue · 欢迎 · ようこそ。是否转换取决于证据和输入要求,不是所有文件的必经处理。
交付并实际运行工具包
启动脚本相对于自身位置查找 reader.py;读取程序同样查找 programme.txt。切换到无关目录,使用启动脚本的绝对路径。可用的交付不应依赖作者当前目录或显式 bash 绕过方式:
cd /tmp
/home/labex/project/event/delivery/start.sh
预期与前面展示的完整四项下午节目完全相同,原始顺序和空白分隔行均保留。此时运行的是实际交付文件。逐一核对 Chloé Martín、林雨、佐藤葵 和 João Silva;退出状态为零本身不能证明文字完整。
返回项目目录:
cd /home/labex/project/event
重试时从 source/ 重新生成受影响的文件。不要把已经转换的 UTF-8 输出再次传给 iconv -f UTF-16,那会错误声明源编码。保留正常文件,每次修改后再次直接启动。其他应用可能接受其他编码或 BOM;这些要求属于此工具包的公开输入约定。
总结
你区分了直接执行权限、shebang 行尾和数据编码,交付并运行了完整的 UTF-8 节目,保留所有姓名、顺序和原本正确的文件。独立晚场挑战使用相同方法,但提供不同的来源证据。



