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

Unix Shell脚本中含空格文件名引用及日期提取方案咨询

解决含空格文件名的循环读取与日期列插入问题

1. 修复循环读取完整文件名的问题

原来的for i in cat files.txt``会把空格、换行都当作字段分隔符,导致文件名被拆分。改用while read循环可正确读取每行完整文件名,推荐IFS= read -r filename的写法,确保保留文件名中的所有空格(包括首尾空格):

#!/bin/bash
while IFS= read -r filename; do
  echo "当前处理文件:$filename"
done < files.txt

2. 从文件名提取月份与年份并转换格式

通过参数扩展拆分文件名中的月份缩写和年份,再用关联数组映射月份缩写到数字格式:

#!/bin/bash
# 定义月份缩写到数字的映射
declare -A month_map=(
  ["JAN"]="01" ["FEB"]="02" ["MAR"]="03"
  ["APR"]="04" ["MAY"]="05" ["JUN"]="06"
  ["JUL"]="07" ["AUG"]="08" ["SEP"]="09"
  ["OCT"]="10" ["NOV"]="11" ["DEC"]="12"
)

while IFS= read -r filename; do
  # 去掉文件名的.txt后缀,得到"JAN 2021"格式的字符串
  base_name=$(basename "$filename" .txt)
  # 拆分月份和年份
  month_str="${base_name% *}"  # 取空格前的部分(月份缩写)
  year="${base_name#* }"       # 取空格后的部分(年份)
  # 获取对应的月份数字
  month_num=${month_map[$month_str]}
  # 生成目标日期字符串,比如"2021-01"格式
  date_str="${year}-${month_num}"
  
  echo "处理文件:$filename,对应日期:$date_str"
done < files.txt

3. 插入日期列到文件每行

得到日期字符串后,使用awk或sed给目标文件的每行添加日期列,以下是两种实现方式:

方法1:用awk添加日期列(推荐,处理空格更稳定)

#!/bin/bash
declare -A month_map=(
  ["JAN"]="01" ["FEB"]="02" ["MAR"]="03"
  ["APR"]="04" ["MAY"]="05" ["JUN"]="06"
  ["JUL"]="07" ["AUG"]="08" ["SEP"]="09"
  ["OCT"]="10" ["NOV"]="11" ["DEC"]="12"
)

while IFS= read -r filename; do
  base_name=$(basename "$filename" .txt)
  month_str="${base_name% *}"
  year="${base_name#* }"
  month_num=${month_map[$month_str]}
  date_str="${year}-${month_num}"
  
  # 在每行开头插入日期(制表符分隔),临时文件替换原文件避免数据丢失
  awk -v date="$date_str" '{print date "\t" $0}' "$filename" > "${filename}.tmp" && mv "${filename}.tmp" "$filename"
done < files.txt

方法2:用sed添加日期列

若文件无特殊正则字符,可简化为sed命令:

# Linux环境
sed -i "s/^/${date_str}\t/" "$filename"
# macOS环境(需加空参数)
sed -i '' "s/^/${date_str}\t/" "$filename"

完整脚本示例

整合所有步骤,包含错误检查的最终脚本:

#!/bin/bash
# 定义月份映射
declare -A month_map=(
  ["JAN"]="01" ["FEB"]="02" ["MAR"]="03"
  ["APR"]="04" ["MAY"]="05" ["JUN"]="06"
  ["JUL"]="07" ["AUG"]="08" ["SEP"]="09"
  ["OCT"]="10" ["NOV"]="11" ["DEC"]="12"
)

# 检查files.txt是否存在
if [ ! -f "files.txt" ]; then
  echo "错误:files.txt不存在"
  exit 1
fi

# 循环处理每个文件
while IFS= read -r filename; do
  # 检查文件是否存在
  if [ ! -f "$filename" ]; then
    echo "警告:文件$filename不存在,跳过"
    continue
  fi

  base_name=$(basename "$filename" .txt)
  month_str="${base_name% *}"
  year="${base_name#* }"
  
  # 检查月份是否在映射中
  if [ -z "${month_map[$month_str]}" ]; then
    echo "警告:无法识别月份$month_str,跳过文件$filename"
    continue
  fi

  month_num=${month_map[$month_str]}
  date_str="${year}-${month_num}"

  # 插入日期列到文件每行开头
  awk -v date="$date_str" '{print date "\t" $0}' "$filename" > "${filename}.tmp" && mv "${filename}.tmp" "$filename"
  echo "已处理文件:$filename,添加日期列:$date_str"
done < files.txt

内容的提问来源于stack exchange,提问作者DataFanatik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 13:20:28