如何在ksh脚本中捕获chown输出

时间:2016-02-03 18:49:50

标签: ksh chown

我编写了一个脚本来根据读入的输入列表更改文件所有权。我的脚本在名称中没有空格的目录上正常工作。但是,它无法更改名称中包含空格的目录上的文件。我还想将chown命令的输出捕获到文件中。有人可以帮忙吗?

这是我在ksh中的脚本:

#!/usr/bin/ksh

newowner=eg27395

dirname=/home/sas/sastest/
logfile=chowner.log
date > $dir$logfile
command="chown $newowner:$newowner"    
for fname in list
do
in="$dirname/$fname"                    
if [[ -e $in  ]]                        
then
     while  read  line
    do
            tmp=$(print "$line"|awk '{if (substr($2,1,1) == "/" )  print $2; if (substr($0,1,1) == "/" )  print '})         
            if [[  -e $tmp  ]]                                                                                     
           then
                    eval  $command \"$tmp\"                                        
             fi
    done < $in
else
        echo "input file $fname is not present. Check file location in the script."
fi
done

3 个答案:

答案 0 :(得分:1)

eval正在剥离此行的引号

command="chown $newowner:$newowner"   

为了让线路与空间一起使用,您需要提供反斜杠报价

command="chown \"$newowner:$newowner\""

这样eval实际运行的命令是

chown "$newowner:$newowner"      

此外,您可能需要围绕此变量设置引用,但您需要调整语法

tmp="$(print "$line"|awk '{if (substr($2,1,1) == "/" )  print $2; if (substr($0,1,1) == "/" )  print '})"

要捕获输出,您可以添加2&gt;&amp; 1&gt; file.out其中file.out是文件的名称...为了让它在使用它时使用eval你需要反斜杠任何特殊字符,就像你需要反斜杠双引号一样< / p>

答案 1 :(得分:1)

其他几个错误:

  • date > $dir$logfile - 未定义$dir变量
  • 安全地从文件中读取:while IFS= read -r line

但是要回答你的主要问题,不要试图动态地建立命令:不要打扰$command变量,不要使用eval,并引用变量。

chmod "$newowner:$newowner" "$tmp"

答案 2 :(得分:1)

您的示例代码表明该列表是一个&#34; meta&#34; file:每个文件的列表,每个文件都有一个要更改的文件列表。当您只有一个文件时,可以删除while循环 当list是包含文件名的变量时,您需要echo "${list}"| while ... 目前还不完全清楚为什么你有时想从第三个字段开始。似乎有时你在文件名之前有两个单词并希望它们被忽略。当文件名也有空格时,在空格上剪切字符串会成为问题。解决方案是查找一个空格后跟斜杠:该空格不是文件名的一部分,可以删除该空间的所有内容。

newowner=eg27395

# The slash on the end is not really part of the dir name, doesn't matter for most commands
dirname=/home/sas/sastest
logfile=chowner.log
# Add braces, quotes and change dir into dirname
date > "${dirname}/${logfile}"

# Line with command not needed

# Is list an inputfile? It is streamed using "< list" at the end of while []; do .. done
while IFS= read -r fname; do
   in="${dirname}/${fname}"
   # Quotes are important
   if [[ -e "$in"   ]]; then
      # get the filenames with a sed construction, and give it to chmod with xargs
      # The sed construction is made for the situation that in a line with a space followed by a slash
      # the filename starts with the slash
      # sed is with # to avoid escaping the slashes
      # Do not redirect the output here but after the loop.
      sed 's#.* /#/#' "${in}" | xargs chmod ${newowner}:${newowner}
   else
       echo "input file ${fname} is not present. Check file location in the script."
   fi
done < list >> "${dirname}/${logfile}"