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

Shell脚本中含空格文件名传递问题:适配mv等外部程序

解决含空格文件名的传递问题

核心问题原因

你用字符串拼接文件名列表的方式本质上不可靠——Bash/mksh在处理$(script)的输出时,会默认按空格、制表符、换行符分割成多个参数,不管文件名里的空格。就算你给文件名加引号,这些引号也会被当成文件名的一部分,自然找不到文件。

解决方案1:用数组存储文件名(适配bash/mksh)

修改脚本,用数组替代字符串保存文件名,能完整保留带空格的文件名:

#!/bin/sh
files=()
for file in *.mp3; do
    # 精准提取艺术家标签,避免多余匹配
    artist=$(ffprobe -hide_banner -of default=noprint_wrappers=1 -show_entries format_tags=artist -i "$file" 2>/dev/null | sed 's/^TAG:artist=//')
    # 根据参数筛选文件
    if [ -n "$1" ]; then
        [ "$artist" = "$1" ] && files+=("$file")
    else
        files+=("$file")
    fi
done

# 按空字符分隔输出,供外部命令安全读取
if [ -n "$1" ]; then
    printf '%s\0' "${files[@]}"
else
    printf '%s\n' "${files[@]}"
fi

调用方式(移动文件)

用xargs -0读取空分隔输出,彻底避免空格分割问题:

./your_script.sh "Marian Hill" | xargs -0 mv -t "Marian Hill"/

-t参数指定目标目录,所有匹配文件会被批量移动过去。

解决方案2:脚本内直接实现扩展功能(更贴合你的需求)

既然要扩展-m/--move、-h/--help等参数,直接在脚本内处理逻辑更方便,还能规避外部参数传递的问题:

#!/bin/sh
move_mode=0
target_artist=""

# 解析命令行参数
while [ $# -gt 0 ]; do
    case "$1" in
        -m|--move)
            move_mode=1
            shift
            ;;
        -h|--help)
            echo "Usage: $0 [OPTIONS] [ARTIST]"
            echo "Options:"
            echo "  -m, --move    Move matching files to artist-named directory"
            echo "  -h, --help    Show this help message"
            exit 0
            ;;
        *)
            target_artist="$1"
            shift
            ;;
    esac
done

# 遍历处理MP3文件
for file in *.mp3; do
    artist=$(ffprobe -hide_banner -of default=noprint_wrappers=1 -show_entries format_tags=artist -i "$file" 2>/dev/null | sed 's/^TAG:artist=//')
    # 筛选指定艺术家的文件(如果有指定)
    if [ -n "$target_artist" ] && [ "$artist" != "$target_artist" ]; then
        continue
    fi

    if [ "$move_mode" -eq 1 ]; then
        # 自动创建艺术家目录(支持带空格的目录名)
        mkdir -p "$artist"
        mv "$file" "$artist/"
    else
        # 默认模式:打印艺术家与对应歌曲
        echo "$artist: $file"
    fi
done

# 额外功能:无参数时列出所有独特艺术家
if [ -z "$target_artist" ] && [ "$move_mode" -eq 0 ]; then
    echo -e "\n=== 所有艺术家 ==="
    ffprobe -hide_banner -of default=noprint_wrappers=1 -show_entries format_tags=artist *.mp3 2>/dev/null | sed 's/^TAG:artist=//' | sort -u
fi

使用示例

  1. 列出所有艺术家及其歌曲:
./your_script.sh
  1. 移动指定艺术家的歌曲:
./your_script.sh -m "Kaito Shoma"
  1. 查看帮助:
./your_script.sh -h

关键细节说明

  • 用ffprobe的format_tags=artist直接提取目标标签,比grep更精准,避免匹配无关内容。
  • mkdir -p确保艺术家目录存在,即使目录名带空格也能正确创建。
  • 数组和空字符分隔是处理带空格/特殊字符文件名的标准做法,完全兼容bash和mksh。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 16:24:19