如何使用 bash 和 sed 操作文件名?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7242832/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I manipulate file names using bash and sed?
提问by Mark
I am trying to loop through all the files in a directory.
我正在尝试遍历目录中的所有文件。
I want to do some stuff on each file (convert it to xml, not included in example), then write the file to a new directory structure.
我想对每个文件做一些事情(将其转换为 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
I want the results to be:
我希望结果是:
$file => /home/devel/stuff/static/2002/hello.txt
$文件 => /home/devel/stuff/static/2002/hello.txt
$newfile => /home/devel/stuff/changethis/2002/hello.txt.xml
$newfile => /home/devel/stuff/changethis/2002/hello.txt.xml
How do I have to change my sedline?
我该如何更改sed线路?
回答by Micha? ?rajer
If you need to rename multiple files, I would suggest to use renamecommand:
如果您需要重命名多个文件,我建议使用rename命令:
# remove "-n" after you verify it is what you need
rename -n 's/hello/hi/g' $(find /home/devel/stuff/static/ -type f)
or, if you don't have renametry this:
或者,如果你没有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
回答by Mu Qiao
Are you trying to change the filename? Then
您是否正在尝试更改文件名?然后
for file in /home/devel/stuff/static/*/*.txt
do
echo "Moving $file"
mv "$file" "${file/static/changethis}.xml"
done
Please make sure /home/devel/stuff/static/*/*.txtis what you want before using the script.
/home/devel/stuff/static/*/*.txt在使用脚本之前,请确保是您想要的。
回答by mouviciel
First, you have to create the name of the new file based on the name of the initial file. The obvious solution is:
首先,您必须根据初始文件的名称创建新文件的名称。显而易见的解决方案是:
newfile=${file/static/changethis}.xml
Second you have to make sure that the new directory exists or create it if not:
其次,您必须确保新目录存在,否则创建它:
mkdir -p $(dirname $newfile)
Then you can do something with your file:
然后你可以对你的文件做一些事情:
doSomething < $file > $newfile
回答by David W.
I wouldn't do the forloop because of the possibility of overloading your command line. Command lines have a limited length, and if you overload it, it'll simply drop off the excess without giving you any warning. It might work if your find returns 100 file. It might work if it returns 1000 files, but it might fail if your find returns 1000 files and you'll never know.
我不会做for循环,因为可能会使您的命令行超载。命令行的长度是有限的,如果你超载它,它会简单地删除多余的,而不会给你任何警告。如果您的 find 返回 100 个文件,它可能会起作用。如果它返回 1000 个文件它可能会工作,但如果您的 find 返回 1000 个文件并且您永远不会知道它可能会失败。
The best way to handle this is to pipe the find into a while read statement as glenn Hymanman.
处理此问题的最佳方法是将 find 管道化为glenn Hymanman的 while read 语句。
The sed command only works on STDIN and on files, but not on file names, so if you want to munge your file name, you'll have to do something like this:
sed 命令仅适用于 STDIN 和文件,但不适用于文件名,因此如果您想修改文件名,则必须执行以下操作:
$newname="$(echo $oldname | sed 's/old/new/')"
to get the new name of the file. The $()construct executes the command and puts the results of the command on STDOUT.
获取文件的新名称。该$()构造执行命令并将命令的结果放在 STDOUT 上。
So, your script will look something like this:
因此,您的脚本将如下所示:
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
Now, since you're renaming the file directory, you'll have to make sure the directory exists before you do your move or copy:
现在,由于您要重命名文件目录,因此在移动或复制之前必须确保该目录存在:
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
Note the quotation marks to handle the case there's a space in the file name.
请注意引号以处理文件名中有空格的情况。
By the way, instead of doing this:
顺便说一句,而不是这样做:
if [ ! -d "$dirname" ]
then
mkdir -p "$dirname"
fi
You can do this:
你可以这样做:
[ -d "$dirname"] || mkdir -p "$dirname"
The ||means to execute the following command only if the test isn't true. Thus, if [ -d "$dirname" ] is a false statement (the directory doesn't exist), you run mkdir.
该||办法执行下面的命令只有在测试是不正确的。因此,如果 [ -d "$dirname" ] 是错误语句(目录不存在),则运行mkdir.
It's a fairly common shortcut when you see shell scripts.
当您看到 shell 脚本时,这是一个相当常见的快捷方式。
回答by Bhargav
OUTPUT="$(pwd)";
for file in `find . -iname "*.pdf"`;
do
echo $file;
cp $file $file.xml
echo "file created in directory = {$OUTPUT}"
done
This will create a new file with name whatyourfilename.xml, for hello.pdf the new file created would be hello.pdf.xml, basically it creates a new file with .xml appended at the end.
这将创建一个名为 whatyourfilename.xml 的新文件,对于 hello.pdf,创建的新文件将是 hello.pdf.xml,基本上它会创建一个新文件,并在末尾附加 .xml。
Remember the above script finds files in the directory /home/devel/stuff/static/whose file names match the matcher string of the find command (in this case *.pdf), and copies it to your present working directory.
请记住,上面的脚本在目录中查找文件/home/devel/stuff/static/名与 find 命令的匹配器字符串匹配的文件(在本例中为 *.pdf),并将其复制到您当前的工作目录中。
The find command in this particular script only finds files with filenames ending with .pdf If you wanted to run this script for files with file names ending with .txt, then you need to change the find command to this find /home/devel/stuff/static/ -iname "*.txt",
此特定脚本中的 find 命令仅查找文件名以 .pdf 结尾的文件 如果您想为文件名以 .txt 结尾的文件运行此脚本,则需要将 find 命令更改为此find /home/devel/stuff/static/ -iname "*.txt",
回答by glenn Hymanman
find ... | while read file; do
newfile=$(basename "$file").xml;
do something to "$file" > "$somedir/$newfile"
done

