Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用bash和sed操作文件名?_Bash_Shell_Sed - Fatal编程技术网

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

如何使用bash和sed操作文件名?,bash,shell,sed,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

我正在尝试循环浏览目录中的所有文件

我想对每个文件做一些工作(将其转换为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
行?

是否要更改文件名?然后

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

在使用脚本之前,请确保
/home/devel/stuff/static/*/*.txt
是您想要的。如果您需要重命名多个文件,我建议使用
重命名
命令:

# remove "-n" after you verify it is what you need
rename -n 's/hello/hi/g' $(find /home/devel/stuff/static/ -type f)
或者,如果您没有
重命名
,请尝试以下操作:

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

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

newfile=${file/static/changethis}.xml
其次,您必须确保新目录存在,如果不存在,则创建新目录:

mkdir -p $(dirname $newfile)
然后,您可以对文件执行以下操作:

doSomething < $file > $newfile
doSomething<$file>$newfile

我不会执行
for
循环,因为可能会使命令行过载。命令行的长度是有限的,如果您重载它,它只会在不给您任何警告的情况下删除多余的命令行。如果您的查找返回100个文件,它可能会起作用。如果它返回1000个文件,它可能会工作,但如果您的查找返回1000个文件,并且您永远不会知道,它可能会失败

处理此问题的最佳方法是将find作为管道传输到while read语句中

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

$newname="$(echo $oldname | sed 's/old/new/')"
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
以获取文件的新名称。
$()
构造执行命令并将命令的结果放在STDOUT上

因此,您的脚本将如下所示:

$newname="$(echo $oldname | sed 's/old/new/')"
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”]是错误的语句(目录不存在),则运行
mkdir

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

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命令的matcher字符串匹配(在本例中为*.pdf),并将其复制到当前的工作目录


此特定脚本中的find命令仅查找文件名以.pdf结尾的文件。如果要对文件名以.txt结尾的文件运行此脚本,则需要将find命令更改为
find/home/devel/stuff/static/-iname“*.txt”

否。我正在尝试获取文件名,追加“.xml”把它放在一个不同的地方directory@Mu乔:您的通配符扩展将丢失静态目录中的任何.txt文件。“查找”命令将不起作用。@Hai Vu,是的,没错。但我不知道op在静态目录中是否有任何txt文件。这就是我让他确认路径是否正确的部分原因。