我运行一个脚本,在目录中生成大约10k个文件。我刚刚发现脚本中有一个错误导致某些文件名有回车符(大概是'\ n'字符)。
我想运行一个sed命令从文件名中删除回车。
任何人都知道哪些params传递给sed以所描述的方式清理文件名?
我正在运行Linux(Ubuntu)
答案 0 :(得分:7)
我不知道sed
将如何做到这一点,但这个python
脚本应该可以解决这个问题:。
这不是sed
,但在执行此类操作时,我发现python
更容易使用:
#!/usr/bin/env python
import os
files = os.listdir('.')
for file in files:
os.rename(file, file.replace('\r', '').replace('\n', ''))
print 'Processed ' + file.replace('\r', '').replace('\n', '')
它会从给定目录中的所有文件名中删除\r
和\n
的所有匹配项。
要运行它,请将其保存到目标目录cd
中(包含要处理的文件),然后运行python /path/to/the/file.py
。
另外,如果您打算进行更多批量重命名,请考虑Métamorphose。对于这些东西来说,这是一个非常好用且功能强大的GUI。并且,它是免费的!
祝你好运!实际上,请尝试:cd
进入目录,输入python
,然后将其粘贴到:
exec("import os\nfor file in os.listdir('.'):\n os.rename(file, file.replace('\\r', '').replace('\\n', ''))\n print 'Processed ' + file.replace('\\r', '').replace('\\n', '')")
它是上一个脚本的单行版本,您无需保存它。
版本2,具有空间替换能力:
#!/usr/bin/env python
import os
for file in os.listdir('.'):
os.rename(file, file.replace('\r', '').replace('\n', '').replace(' ', '_')
print 'Processed ' + file.replace('\r', '').replace('\n', '')
这是单线:
exec("import os\nfor file in os.listdir('.'):\n os.rename(file, file.replace('\\r', '').replace('\\n', '')replace(' ', '_'))\n print 'Processed ' + file.replace('\\r', '').replace('\\n', '');")
答案 1 :(得分:4)
如果文件名中没有空格,您可以执行以下操作:
for f in *$'\n'; do mv "$f" $f; done
如果嵌入了换行符,它将无效,但它可用于尾随换行符。
如果您必须使用sed
:
for f in *$'\n'; do mv "$f" "$(echo "$f" | sed '/^$/d')"; done
使用rename
Perl脚本:
rename 's/\n//g' *$'\n'
或util-linux-ng实用程序:
rename $'\n' '' *$'\n'
如果该字符是返回而不是换行符,请在上面显示的任何位置将\n
或^$
更改为\r
。
答案 2 :(得分:2)
编辑:如果您真的想要sed
,请看一下:
这些行中的某些内容应与下面的perl
类似:
for i in *; do echo mv "$i" `echo "$i"|sed ':a;N;s/\n//;ta'`; done
使用perl,尝试以下几点:
for i in *; do mv "$i" `echo "$i"|perl -pe 's/\n//g'`; done
这将通过从中删除所有换行符来重命名当前文件夹中的所有文件。如果你需要递归,你可以使用find
代替 - 在这种情况下要注意转义。
答案 3 :(得分:2)
您没有得到任何纯粹的sed
答案的原因是从根本上sed
编辑文件内容,而不是文件名;因此,使用sed的答案都会执行诸如将文件名回显到管道(伪文件),使用sed
进行编辑,然后使用mv
将其转换回文件名。
由于sed
已经出来,这里有一个pure-bash版本,可以添加到目前为止的Perl,Python等脚本中:
killpattern=$'[\r\n]' # remove both carriage returns and linefeeds
for f in *; do
if [[ "$f" == *$killpattern* ]]; then
mv "$f" "${f//$killpattern/}"
fi
done
...但由于${var//pattern/replacement}
sh
中没有[[...]]
(以及sh
),因此这是使用tr
的版本 - 仅语法和{{ 1}}进行角色替换:
for f in *; do
new="$(printf %s "$f" | tr -d "\r\n")"
if [ "$f" != "$new" ]; then
mv "$f" "$new"
fi
done
答案 4 :(得分:0)
实际上有一种方法可以使用sed:
carr='\n' # specify carriage return
files=( $(ls -f) ) # array of files in current dir
for i in ${files[@]}
do
if [[ -n $(echo "$i" | grep $carr) ]] # filenames with carriage return
then
mv "$i" "$(echo "$i" | sed 's/\\n//g')" # move!
fi
done
这实际上有效。