【问题标题】:Simplest, Safe Method for Trimming File Paths修剪文件路径的最简单、安全的方法
【发布时间】:2014-02-24 13:02:59
【问题描述】:

我有一个执行大量文件处理的脚本,为了安全起见,使用空字符作为分隔符接收其路径就足够了。

但是,它将所有路径都作为绝对路径处理(省去了一些麻烦),但是出于输出目的,这些路径有点笨拙,所以我想从输出中删除一部分路径。现在,我想到了很多选择,但困难在于以一种对我可能遇到的任意路径安全的方式使用它们,这就是事情变得有点棘手的地方。

这是一个简单的例子:

#!/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

因此,在上面的脚本中,我想以最兼容的方式(例如 - 没有特定于 bash 的方式)从其中删除 path 并从中删除 TARGET,它需要能够删除 only em> 从字符串的开头,即 - /foo/bar 变为 bar/foo/bar/foo 变为 bar/foo/bar/foo 仍然是 /bar/foo。它还应该处理文件名中任何可能的字符,包括一些文件系统支持的字符,如波浪线、冒号等,以及讨厌的倒引号字符。

我使用sed 拼凑了一些混乱的解决方案,首先转义任何可能破坏我的正则表达式的字符,但这是一种非常混乱的做事方式,所以我希望有一些更简单的方法.如果没有,到目前为止的解决方案如下:

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

除了那些字符之外,我可能还缺少一些我应该转义的字符,并对任何拼写错误表示歉意。

【问题讨论】:

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

标签: regex shell filepath


【解决方案1】:

要从字符串中删除前缀,

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

用于参数扩展的 # 运算符是 POSIX 标准的一部分,可在任何符合 POSIX 标准的 shell 中工作。

【讨论】:

  • 这似乎是最好的方法,但不幸的是我认为我的 shell 环境(在 OS X 上)正在使用ash。它支持一些 bash-isms,但是当我使用此方法修剪路径时它不会引发错误,它也不起作用(只返回完整的、未修改的路径)。任何想法为什么会这样?我原以为它会引发某种错误。
  • 抱歉,刚刚检查过,OS X 确实使用 bash 来编写 shell 脚本,但由于某些原因,不支持各种 bash 特定功能,在终端中使用时效果很好。我想我可以通过bash 而不是sh 运行我的脚本,工作环境非常奇怪!
  • bash 被调用为sh 时,某些bash 特定的功能会被抑制,但这里不应该是这种情况。正如我在回答中指出的那样,# 不是bashism。您能否添加一个无效的 TARGET/path 对的具体示例?
【解决方案2】:

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

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

【讨论】:

  • 感谢您的建议,但实际上我更喜欢在处理它时将$path 保留为绝对路径,我只想修剪$TARGET 以用于输出目的,我会相应地澄清我的示例.另外,我不确定管道字符是否也适用于 sed,因为例如 HFS 会很乐意在文件名中允许管道字符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-25
  • 1970-01-01
  • 2010-09-29
  • 2014-12-17
  • 2014-05-24
  • 2018-06-01
  • 1970-01-01
相关资源
最近更新 更多