所以我删除文件名中的特殊字符并用空格替换。除了其中包含单反斜杠的文件外,我已经开始工作了。 注意这些文件在Finder中创建了OS X删除反斜杠与tr
old_name="testing\this\folder"
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
这将导致NEW_NAME被“测试hisolder” 如何我只是删除了反斜杠,而不是前面的字符?
所以我删除文件名中的特殊字符并用空格替换。除了其中包含单反斜杠的文件外,我已经开始工作了。 注意这些文件在Finder中创建了OS X删除反斜杠与tr
old_name="testing\this\folder"
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
这将导致NEW_NAME被“测试hisolder” 如何我只是删除了反斜杠,而不是前面的字符?
这将导致NEW_NAME被 “测试hisolder”
这个字符串看起来像echo -e "testing\this\folder"
的结果,因为\t
和\f
实际上取代用制表符和换页控制字符。
也许你有一个别名像alias echo='echo -e'
,或者可能的echo
在外壳的版本执行解释反斜杠:
POSIX不需要任何选项的支持,并且说的 行为如果任何STRING包含 反斜杠或第一个参数为“-n”,则'echo'是实现定义的。如果便携式程序需要省略尾部换行符或输出控制字符或反斜杠,则可以使用'printf'命令使用 。
(从信息页)
所以,你应该在新的软件使用printf
,而不是echo
。特别是,echo $old_name
应替换为printf %s "$old_name"
。
例如this discussion有一个很好的解释。
无需printf
正如@ mklement0建议,您可以通过Bash here string的手段避免管道:
tr '<>:\\#%|?*' ' ' <<<"$old_name"
使用bash,你可以使用参数扩展:
$ old_name="testing\this\folder"
$ new_name=${old_name//[<>:\\#%|?*]/ }
$ echo $new_name
testing this folder
有关详细信息,请参阅猛砸手册上shell parameter expansion。
我认为你的测试用例丢失了\
的正确转义,所以你并不真正测试包含在字符串中的反斜杠的情况。
这为我工作:
old_name='testing\\this\\folder'
new_name=$(echo $old_name | tr '<>:\\#%|?*' ' ');
echo $new_name
# testing this folder
在Bash(这是如何标记问题)中使用默认选项,使用它的'echo'内建,这将保留_both_反斜杠,并且结果字符串在单词之间会有_2_空格。 (相反,OP的代码应该按原样工作。)除此之外,“$ old_name”应该用双引号。你的转义只能在打开(隐式或显式)选项'xpg_echo'的情况下才能起作用,但更好的解决方案是使用'printf'或一个here-string。 – mklement0
Ruslan's excellent answer解释了为什么你的命令可能不会为你工作,并提供强大的便携式解决方案。
TL;博士:
sh
而非bash
(即使在MacOS sh
这是Bash的化身)跑了你的代码,或者你有shell选项xpg_echo
明确地打开。printf
而不是echo
。在bash,使用默认选项,并使用echo
内置,命令将正常运行,是(除了你应该用双引号$old_name
稳健性),因为echo
(默认设置)不在其操作数中扩展转义序列,如\t
。
然而,bash的echo
可以进行扩大控制字符转义序列:
shopt -s xpg_echo
sh
或与--posix
选项( ,以及其他选项和行为变化,激活xpg_echo
)因此,您的s例如,ymptom可能是由脚本以脚本行#!/bin/sh
运行代码引起的。
但是,如果你的目标sh
,即,如果你正在写一个便携式脚本,然后echo
应该完全避免的原因恰恰是它的行为跨越炮弹和平台的不同 - 见鲁斯兰的printf
解决方案。
顺便说一句:或许是一个更强大的方式来你tr
命令是白名单方法:仅指出明确允许在结果中的字符,并排除其他与-C
选项:
old_name='testing\this\folder'
new_name=$(printf '%s' "$old_name" | tr -C '[:alnum:]_-' ' ')
这样,任何不是字母,数字,_
或-
的字符都将替换为空格。
感谢您的详细解释 – rndy
根据你如何定义_special characters_,你可以使用'tr -d'[:punct:]'' –