如何使用bash和sed操作文件名?

时间:2011-08-30 12:02:05

标签: bash shell sed

我正在尝试遍历目录中的所有文件。

我想在每个文件上做一些事情(将其转换为xml,未包括在示例中),然后将文件写入新的目录结构。

for file in `find /home/devel/stuff/static/ -iname "*.pdf"`;
do
  echo $file;
  sed -e 's/static/changethis/' $file > newfile +".xml";
  echo $newfile;
done

我希望结果为:

$ file => /home/devel/stuff/static/2002/hello.txt

$ newfile => /home/devel/stuff/changethis/2002/hello.txt.xml

如何更改sed行?

6 个答案:

答案 0 :(得分:5)

如果您需要重命名多个文件,我建议使用rename命令:

# remove "-n" after you verify it is what you need
rename -n 's/hello/hi/g' $(find /home/devel/stuff/static/ -type f)

或者,如果您没有rename,请尝试:

find /home/devel/stuff/static/ -type f | while read FILE
do
    # modify line below to do what you need, then remove leading "echo" 
    echo mv $FILE $(echo $FILE | sed 's/hello/hi/g')
done

答案 1 :(得分:3)

您是否尝试更改文件名?然后

for file in /home/devel/stuff/static/*/*.txt
do
    echo "Moving $file"
    mv "$file" "${file/static/changethis}.xml"
done

在使用脚本之前,请确保/home/devel/stuff/static/*/*.txt符合您的要求。

答案 2 :(得分:1)

首先,您必须根据初始文件的名称创建新文件的名称。显而易见的解决方案是:

newfile=${file/static/changethis}.xml

其次,您必须确保新目录存在,否则创建它:

mkdir -p $(dirname $newfile)

然后你可以对你的文件做点什么:

doSomething < $file > $newfile

答案 3 :(得分:1)

我不会执行for循环,因为可能会使命令行超载。命令行的长度有限,如果你超载它,它只会丢弃多余的而不会给你任何警告。如果您的查找返回100个文件,它可能会有效。如果它返回1000个文件可能会有效,但如果你的find返回1000个文件并且你永远不知道它可能会失败。

处理此问题的最佳方法是将查找作为glenn jackman传递给while读取语句。

sed命令仅适用于STDIN和文件,但不适用于文件名,因此如果您想要使用文件名,则必须执行以下操作:

$newname="$(echo $oldname | sed 's/old/new/')"

获取文件的新名称。 $()构造执行命令并将命令的结果放在STDOUT上。

所以,你的脚本看起来像这样:

find /home/devel/stuff/static/ -name "*.pdf" | while read $file
do
    echo $file;
    newfile="$(echo $file | sed -e 's/static/changethis/')"
    newfile="$newfile.xml"
    echo $newfile;
 done

现在,由于您正在重命名文件目录,因此在移动或复制之前,您必须确保该目录存在:

find /home/devel/stuff/static/ -name "*.pdf" | while read $file
do
    echo $file;
    newfile="$(echo $file | sed -e 's/static/changethis/')"
    newfile="$newfile.xml"
    echo $newfile;

    #Check for directory and create it if it doesn't exist
    $dirname=$(dirname "$newfile")
    if [ ! -d "$dirname" ]
    then
        mkdir -p "$dirname"
    fi

    #Directory now exists, so you can do the move
    mv "$file" "$newfile"
 done

请注意引号以处理文件名中有空格的情况。

顺便说一句,而不是这样做:

if [ ! -d "$dirname" ]
then
    mkdir -p "$dirname"
fi

你可以这样做:

[ -d "$dirname"] || mkdir -p "$dirname"

||表示仅在测试不为真时才执行以下命令。因此,如果[-d“$ dirname”]是一个false语句(该目录不存在),则运行mkdir

当您看到shell脚本时,这是一个相当常见的快捷方式。

答案 4 :(得分:0)

find ... | while read file; do
  newfile=$(basename "$file").xml;
  do something to "$file" > "$somedir/$newfile"
done

答案 5 :(得分:0)

OUTPUT="$(pwd)";
for file in `find . -iname "*.pdf"`;
do
  echo $file;
  cp $file $file.xml
  echo "file created in directory = {$OUTPUT}"
done

这将创建一个名为whatyourfilename.xml的新文件,对于hello.pdf,创建的新文件将是hello.pdf.xml,基本上它会在末尾创建一个附加.xml的新文件。

请记住,上面的脚本在目录/home/devel/stuff/static/中找到文件名与find命令的匹配器字符串匹配的文件(在本例中为* .pdf),并将其复制到您当前的工作目录。

此特定脚本中的find命令仅查找文件名以.pdf结尾的文件如果要为文件名以.txt结尾的文件运行此脚本,则需要将find命令更改为此{{1} },