如何从文件读取文件名并以|为分隔符存储文件名与内容至另一文件
问题描述
我在Windows机器上使用Bash shell,TestDir目录下有Filenames.txt、File1.txt、File2.txt、File3.txt这几个文件。其中Filenames.txt里记录了其他文本文件的名称:
Cat Filenames.txt
File1.txt
File2.txt
File3.txt
各文件内容如下:
Cat File1.txt
This is content of File1
Cat File2.txt
This is content of File2
Cat File3.txt
This is content of File3
我希望生成Outputfile.txt,格式要求如下:
Cat Outputfile.txt
File1|This is content of File1
File2|This is content of File2
File3|This is content of File3
我尝试了下面的Bash脚本,但运行报错:
#!/usr/bin/env bash file=$(cat Filenames.txt) y=$(pwd) for line in $file do x=$(cat "${line}") echo -e "${line}"|"${x}" >> Outputfile.txt done
错误信息:
$ bash Script.sh cat: 'file1.txt'$'\r': No such file or directory Script.sh: line 7: : command not found cat: 'file2.txt'$'\r': No such file or directory Script.sh: line 7: : command not found Script.sh: line 7: This is content of File3: command not found
当前生成的Outputfile.txt内容:
test1_file | test2_file | test3_file|
请帮忙解决这个问题。
问题原因及修复方案
1. Windows换行符导致文件名识别错误
Windows文本文件用\r\n(CRLF)作为换行符,而Bash环境默认识别\n(LF)。Filenames.txt每行末尾带的\r字符,让Bash把文件名识别成File1.txt\r,自然找不到对应文件。
修复:
执行命令清理换行符:
# 若有dos2unix工具 dos2unix Filenames.txt # 若无dos2unix,用sed替代 sed -i 's/\r$//' Filenames.txt
2. 管道符未转义触发语法错误
脚本中echo -e "${line}"|"${x}"里的|是管道符,Bash会将其视为命令分隔符,试图把echo的输出传给"${x}"执行,导致command not found错误。
修复:
将管道符包含在字符串内,或用printf更可靠:
# 方式1:直接拼接字符串 echo -e "${line}|${x}" >> Outputfile.txt # 方式2:推荐用printf,格式更稳定 printf "%s|%s\n" "${line}" "${x}" >> Outputfile.txt
3. 循环读取文件的方式不够可靠
用for line in $file读取文件内容,若文件名或内容含空格会出错,改用while read循环更稳妥。
最终修复后的脚本
#!/usr/bin/env bash # 清空目标文件(避免重复追加) > Outputfile.txt # 清理Filenames.txt的Windows换行符 sed -i 's/\r$//' Filenames.txt # 逐行读取文件名并处理 while IFS= read -r filename do content=$(cat "$filename") printf "%s|%s\n" "$filename" "$content" >> Outputfile.txt done < Filenames.txt
内容的提问来源于stack exchange,提问作者Sooraj P George

