用于修复目录中文件名的sed命令

时间:2010-12-11 16:11:57

标签: bash ubuntu sed

我运行一个脚本,在目录中生成大约10k个文件。我刚刚发现脚本中有一个错误导致某些文件名有回车符(大概是'\ n'字符)。

我想运行一个sed命令从文件名中删除回车。

任何人都知道哪些params传递给sed以所描述的方式清理文件名?

我正在运行Linux(Ubuntu)

5 个答案:

答案 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

这实际上有效。