2014-02-24 35 views
0

我有一个脚本,它执行大量的文件处理,并且它足够接收使用空字符作为安全分隔符的路径。但是,它将所有路径处理为绝对路径(节省一些头痛),但是对于输出目的来说这些路径有点不便,所以我想从输出中删除一部分路径。现在,有很多选项值得思考,但难点在于以一种对我可能遇到的任意路径安全的方式使用这些选项,这就是事情变得棘手的地方。修剪文件路径的最简单,安全的方法

这里有一个简单的例子:

#!/bin/sh 
TARGET="$1" 
find "$TARGET" -print0 | while IFS= read -rd '' path; do 
    # Process path for output here 
    path_str="$path" 
    echo "$path_str" 
done 

所以在上面的脚本我想借此path并拆除TARGET,在可能的最兼容的方式(例如 - 具体什么bash)的,它需要能够从字符串的开头仅删除,即 - /foo/bar变为bar/foo/bar/foo变成bar/foo/bar/foo仍然是/bar/foo。它还应该处理文件名中的任何可能的字符,包括某些文件系统支持的字符,例如tildes,冒号等,以及讨厌的反引号字符。

我使用sed首先转义了任何可能会破坏我的正则表达式的字符,但是这是一个非常混乱的做法,所以我希望有一些更简单的方法。如果没有的话,这里的解决方案是迄今:

SAFE_CHARS='s:\([[/.*]\):\\\1:g' 
target_safe=$(printf '%s' "$TARGET" | sed "$SAFE_CHARS") 
path_str=$(printf '%s' "$path" | sed "s/^$target_safe//g') 

有可能是几个字符缺失,我应该除了那些那些被逃脱,和任何错别字道歉。

+0

'read'的'-d'选项是'bash'特定的(或者至少不是POSIX标准的一部分)。如果你使用它,你也可以使用其他'bash'扩展。 – chepner

回答

0

你可以试试这个简单的查找:

export TARGET="$1" 
find "$TARGET" -exec bash -c 'sed "s|^$TARGET\/||" <<< "$1"' - '{}' \; 
+0

感谢您的建议,但我实际上更喜欢在工作时将'$ path'保留为绝对路径,我只是为了输出目的而修剪'$ TARGET',我会相应地澄清我的示例。另外,我不确定管道字符是否也适用于'sed',因为例如HFS会高兴地允许在文件名中使用管道字符。 – Haravikk

1

从字符串中删除前缀,

$ TARGET=/foo/ 
$ path=/foo/bar 
$ echo "${path#$TARGET}" 
bar 

#运营商参数扩展是POSIX标准的一部分,将在任何工作符合POSIX标准的外壳。

+0

这似乎是最好的方法,但不幸的是我认为我的shell环境(在OS X上)使用'ash'。它支持一些bash-isms,但是当我使用此方法修剪路径时不会引发错误,但它也不起作用(只是返回完整的,未修改的路径)。任何想法,为什么这可能是?我以为它会抛出某种错误。 – Haravikk

+0

对不起,刚刚检查过OS X确实使用'bash'作为shell脚本,但由于某种原因,各种bash特有的功能不被支持,在终端中使用时工作得很好。我想我可以通过'bash'而不是'sh'来运行我的脚本,这是非常奇怪的工作环境! – Haravikk

+0

当'bash'被调用为'sh'时,某些'bash'特有的特性被抑制,但这不应该是这种情况。正如我在我的回答中指出的那样,'#'不是'bash'ism。你可以添加一个不适用的'TARGET' /'path'对的特定示例吗? – chepner