2013-04-25 76 views
1

我有一个错误试图找到一种方法,用另一个字符串转换文件路径转换为字符串

sed: Error tryning to read from {directory_path}: It's a directory 

shell脚本

#!/bin/sh 

R2K_SOURCE="source/" 
R2K_PROCESSED="processed/" 
R2K_TEMP_DIR="" 

echo " Procesando archivos desde $R2K_SOURCE " 

for file in $(find $R2K_SOURCE) 
do 
     if [ -d $file ] 
     then 
       R2K_TEMP_DIR=$(sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file) 
       echo "directorio $R2K_TEMP_DIR" 
     else 
#    some code executes 
       : 
     fi 
done 

# find $R2K_PROCCESED -type f -size -200c -delete 

我”替换目录路径的字符串米的理解是,这是该行的RROR

R2K_TEMP_DIR=$(sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file) 

,但我不知道怎么跟sh能治疗$文件变量作为字符串nd不是一个目录对象。

+1

可能是:'R2K_TEMP_DIR = $(echo $ file | sed's /“$ R2K_SOURCE”/“$ R2K_PROCESSED”/ g')'(尽管您可以指示find来通过'-type独立查找目录和文件f' /'-type d' – Wrikken 2013-04-25 19:05:02

+0

@Wrikken它的作品现在写出来就像一个答案,y会批准你的答案。非常感谢 – Rafael 2013-04-25 19:09:40

+0

Loetar的答案是更正确的,然后我的快速评论;) – Wrikken 2013-04-25 19:12:14

回答

3

首先,不要使用:

for item in $(find ...) 

因为你可能会重载命令行。此外,for循环无法启动,直到$(...)中的进程结束。相反:

find ... | while read item 

您还需要注意时髦的文件名。 for循环会在其中有空格的所有文件中咳嗽。只要文件名中只有一个空格而不是双空格,则find | while就可以工作。更好:

find ... -print0 | while read -d '' -r item 

这将使空文件名之间,并read将打破这些空值。这样,带空格,制表符,换行符或其他任何可能导致问题的文件都可以毫无问题地被读取。

你sed的路线是:

R2K_TEMP_DIR=$(sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file) 

这是什么尝试做的是编辑$file这是一个目录。你想要做的是将目录名称本身。因此,你必须名称呼应成sed为管道:

R2K_TEMP_DIR=$(echo $file | sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g') 

但是,您可能使用环境变量参数来筛选你的环境变量会更好。

基本上,您有一个名为source/的目录,您正在查找的所有文件都位于该目录下。您只需要换:

source/foo/bar 

processed/foo/bar 

你可以做这样的事情$ {文件#源/}。 #表示这是一个左侧过滤器,它将移除最少量以匹配#之后的glob表达式。检查bash的联机帮助页,并在参数扩展下查看。在它的位置

#!/bin/sh 

R2K_SOURCE="source/" 
R2K_PROCESSED="processed/" 
R2K_TEMP_DIR="" 

echo " Procesando archivos desde $R2K_SOURCE " 

find $R2K_SOURCE -print0 | while read -d '' -r file 
do 
    if [ -d $file ] 
    then 
     R2K_TEMP_DIR="processed/${file#source/}" 
     echo "directorio $R2K_TEMP_DIR" 
    else 
#  some code executes 
     : 
    fi 
done 

R2K_TEMP_DIR="processed/${file#source/}"去除的$file开始的source/,你只是在前面加上processed/

这一点,你可以做这样的事情。

更好的是,它的效率更高。在您的原始脚本中,$(..)会创建另一个shell进程来运行您的echo,然后将其导出到另一个进程以运行sed。 (假设你使用loentar的解决方案)。您不再有任何子流程在运行。您的目录名称的整个修改是内部的。

顺便说一句,这也应太:

R2K_TEMP_DIR="$R2K_PROCESSED/${file#$R2K_SOURCE}" 

我只是没有测试。

+0

使用这种类型的字符串替换'R2K_TEMP_DIR =“$ R2K_PROCESSED/$ {file#$ R2K_SOURCE}”'我怎样才能从文件路径基于扩展名前缀(.mib,.MIB ,.我的)等等。我最后一次尝试它是R2K_NEW_FILE =“$ {$ R2K_TEMP_DIR%$ MIB_EXTENTIONS}” 其中MIB_EXTENTION =“。mib | .MIB | .my” – Rafael 2013-04-25 22:56:53

+0

这些是g lobs而不是正则表达式。您可以执行'$ {file%。*}',这将删除所有扩展名。您也可以执行'$ {file%。*(mib | MIB | my)}'来仅删除特定的表达式。请注意,它是'*(ext1 | ext2 | ext3)',在BASH中,您必须使用'shopt -s extglob'才能使用这些扩展表达式。 – 2013-04-26 04:21:25

8

如果你想ot替换路径名的一部分,你可以回显路径名并将它带到管道上的sed。 还必须允许将sed命令到双引号,而不是单一的和变化的分隔符的'命令一样,通配符:

R2K_TEMP_DIR=$(echo "$file" | sed "s:$R2K_SOURCE:$R2K_PROCESSED:g") 

然后你就可以用里面的'命令斜线操作。

更新:

更妙的是去除无用的回声,并使用 “这里是字符串”,而不是:

R2K_TEMP_DIR=$(sed "s:$R2K_SOURCE:$R2K_PROCESSED:g" <<< "$file") 
+0

更好的答案:D – Rafael 2013-04-25 19:14:02

+0

真的很酷将记住,现在 – Vahid 2013-04-25 19:27:16