diff --git a/vipsong.py b/vipsong.py index 2659135..39c83ea 100644 --- a/vipsong.py +++ b/vipsong.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -import os, sys, glob, struct, base64, json, io +import os, sys, glob, struct, base64, json, io, re from pathlib import Path from typing import Optional from Crypto.Cipher import AES @@ -86,6 +86,9 @@ def _parse_gt_output(input_path, output_spec): """解析 'input>output' 重定向语法,返回 (output_path, output_fmt)。""" p = Path(input_path) spec = output_spec.strip() + # 规范化路径分隔符后的空格(如 '../ file.mp3' -> '../file.mp3'), + # 保留文件名内部的空格 + spec = re.sub(r'([/\\])\s+', r'\1', spec) if not spec: # 空输出规格(如 'song.ncm>'),使用默认 mp3 格式 out_path = p.with_suffix(".mp3") @@ -466,20 +469,32 @@ def print_stats(): print() def _split_line(line): - """按空白分割命令行,处理引号但不处理反斜杠转义(适配 Windows 路径)。""" + """按空白分割命令行,处理引号。支持 '>' 重定向语法:> 后的输出路径可含空格。 + + 注意:'>' 后的内容(含空格)作为输出路径整体;参数请写在重定向前。 + """ args = [] current = [] in_single = False in_double = False + after_redirect = False # 是否进入 > 重定向输出模式 for ch in line: if ch == '"' and not in_single: in_double = not in_double elif ch == "'" and not in_double: in_single = not in_single + elif ch == '>' and not in_single and not in_double: + # 遇到 > 重定向:附加到当前 token,进入输出模式(保留空格) + after_redirect = True + current.append(ch) elif ch in (' ', '\t') and not in_single and not in_double: - if current: - args.append(''.join(current)) - current = [] + if after_redirect: + # 输出路径模式:保留空格(用于含空格的文件名) + current.append(ch) + else: + if current: + args.append(''.join(current)) + current = [] else: current.append(ch) if current: