我在尝试找到用另一个字符串
替换目录路径中的字符串时遇到错误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
我理解这行中的错误
R2K_TEMP_DIR=$( sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file )
但我不知道如何告诉sh将$ file变量视为字符串而不是目录对象。
答案 0 :(得分:8)
如果你想要替换路径名的一部分,你可以回显路径名并将其带到sed over pipe。 此外,您必须通过将sed命令放入双引号而不是单引号来启用globbing,并为's'命令更改分隔符,如下所示:
R2K_TEMP_DIR=$(echo "$file" | sed "s:$R2K_SOURCE:$R2K_PROCESSED:g")
然后你就可以在's'命令中使用斜杠进行操作。
更新
更好的是删除无用的回声并使用“here is string”代替:
R2K_TEMP_DIR=$(sed "s:$R2K_SOURCE:$R2K_PROCESSED:g" <<< "$file")
答案 1 :(得分:3)
首先,不要使用:
for item in $(find ...)
因为您可能会重载命令行。此外,在$(...)
中的进程完成之前,for循环无法启动。代替:
find ... | while read item
您还需要注意时髦的文件名。 for
循环将咳嗽所有带有空格的文件。只要文件名称中只有一个空格而不是双重空格,find | while
就可以正常工作。更好:
find ... -print0 | while read -d '' -r item
这将在文件名之间放置空值,read
将在这些空值上中断。这样,可以毫无问题地读取包含空格,制表符,换行符或其他任何可能导致问题的文件。
你的上线是:
R2K_TEMP_DIR=$( sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g' $file )
这是尝试做的是编辑您的$file
这是一个目录。你想要做的是munge目录名称本身。因此,您必须将名称作为管道回显到sed
:
R2K_TEMP_DIR=$(echo $file | sed 's/"$R2K_SOURCE"/"$R2K_PROCESSED"/g')
但是,最好使用环境变量参数来过滤环境变量。
基本上,您有一个名为source/
的目录,您要查找的所有文件都在该目录下。你只想改变:
source/foo/bar
到
processed/foo/bar
您可以执行类似$ {file#source /}的操作。 #
表示这是左侧过滤器,它将删除与#
之后的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/}"
从source/
开头删除$file
,您只需将processed/
添加到其位置。
更好的是,它的效率更高。在原始脚本中,$(..)
创建另一个shell进程来运行echo
,然后在其中导出到另一个进程以运行sed
。 (假设你使用loentar的解决方案)。您不再运行任何子进程。您的目录名称的整个修改是内部的。
顺便说一句,这也应该有效:
R2K_TEMP_DIR="$R2K_PROCESSED/${file#$R2K_SOURCE}"
我只是没有测试过。