批量替换空格特殊符号文件名的脚本

比如下面csv目录中的文件
lf-orders-2018-11-20(1700).csv
lf-orders-2018-11-20 17002.csv

文件名中带有空格,和夹杂着中英文圆括号,需要将他们替换为下划线_
生成下面的:
lf-orders-2018-11-20_1700_.csv
lf-orders-2018-11-20_17002.csv

SAVEIFS=$IFS
IFS=$'\n'
for file in `ls csv | grep .csv`
do
 newfile=`echo ${file} | sed 's/ /_/g'| sed 's/(/_/g'| sed 's/)/_/g'`
 # echo $newfile
 mv csv/$file csv/$newfile
done
# revert IFS
IFS=$SAVEIFS

我现在已经有了上面的脚本,不太好用,
会报mv: cannot stat 'csv/lf-orders-2018-11-20 17002 .csv'$'\n''lf-orders-2018-11-20'$'\357\274\210''1700).csv': No such file or directory

求更简洁的写法,谢谢!

阅读 5.8k
4 个回答

rename命令了解下

把下面两条命令在csv文件所在目录都执行一下。

ls *.csv|sed -r 's/(.*)(([^)]+)\)(.*)/mv "&" \1_\2_\3/e'
ls *.csv|sed -r 's/(.*)\s+(.*)/mv "&" \1_\2/e'

测试:
图片描述

回答题主评论里的问题,远程到别的机器上执行方法:

ssh lft "ls csv/*.csv|sed -r 's/(.*)(([^)]+)\)(.*)/mv \"&\" \1_\2_\3/e'"
ssh lft "ls csv/*.csv|sed -r 's/(.*)\s+(.*)/mv \"&\" \1_\2/e'"

既然你都打算用脚本来处理了,那为啥不用python呢?
python轻松搞定,脚本如下:

#!/usr/bin/env python3
#-*- coding: utf-8 -*-

import sys
import os
import re

def main():

    path = sys.argv[1]
    for dirpath, dirnames, filenames in os.walk(path):
        for filename in filenames:
            newname = re.sub('[  \((]+', '_', filename)
            newname = re.sub('[\))]+', '', newname)
            if filename != newname:
                print('rename> {}: {} => {}'.format(dirpath, filename, newname))
                os.rename(os.path.join(dirpath, filename), os.path.join(dirpath, newname))

if __name__ == '__main__':
    main()

测试执行结果如下:

$ find csv
csv
csv/lf-orders-2018-11-20 17002.csv
csv/ccc
csv/ccc/lf-orders-2018-11-20 17002.csv
csv/ccc/csv
csv/ccc/csv/lf-orders-2018-11-20 17002.csv
csv/ccc/csv/ccc
csv/ccc/csv/ccc/lf-orders-2018-11-20 17002.csv
csv/lf-orders-2018-11-20(1700).csv
$ ./z.py csv
rename> csv: lf-orders-2018-11-20 17002.csv => lf-orders-2018-11-20_17002.csv
rename> csv: lf-orders-2018-11-20(1700).csv => lf-orders-2018-11-20_1700.csv
rename> csv/ccc: lf-orders-2018-11-20 17002.csv => lf-orders-2018-11-20_17002.csv
rename> csv/ccc/csv: lf-orders-2018-11-20 17002.csv => lf-orders-2018-11-20_17002.csv
rename> csv/ccc/csv/ccc: lf-orders-2018-11-20 17002.csv => lf-orders-2018-11-20_17002.csv
$ find csv
csv
csv/lf-orders-2018-11-20_17002.csv
csv/ccc
csv/ccc/lf-orders-2018-11-20_17002.csv
csv/ccc/csv
csv/ccc/csv/lf-orders-2018-11-20_17002.csv
csv/ccc/csv/ccc
csv/ccc/csv/ccc/lf-orders-2018-11-20_17002.csv
csv/lf-orders-2018-11-20_1700.csv
for name in ./*;do mv "${name}" "${name// /}";done

一行 shell 的事....干嘛整那么麻烦

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题