Linux shell Using sed how to batch change filename detail
- 2020-06-15 11:00:02
- OfStack
preface
This article mainly introduces Linux shell to use sed batch to change the file name of the relevant content, share for your reference and learning, the following words do not say much, let's look at a detailed introduction.
The sample
Remove specific character
Objective: Change 2017-01-01.jpg, 2018-01-01.jpg to 20170101.jpg, 20180101.jpg
Method: Replace all - with null
for file in `ls | grep .jpg`
do
newfile=`echo $file | sed 's/-//g'`
mv $file $newfile
done
sed is used here for string replacement of standard output in the following general format:
stdout | sed 's/pattern/replace/'
In the example above, add g at the end to replace all matches, not just the first.
Intermediate insertion character
Objective: To change book01.ES33en and paper02.ES35en to book-01.ES37en and ES38en-02.ES39en
Method: Get the string on both sides of the position to be inserted by grouping match, and replace it by reverse reference
for file in `ls | grep .txt`
do
newfile=`echo $file | sed 's/\([a-z]\+\)\([0-9]\+\)/\1-\2/'`
mv $file $newfile
done
Analysis of the
The example above starts with the ls and grep commands to get the list of files to be renamed, then replaces the string with the sed command, and finally completes the filename change using the mv command.
There are many ways to get a list of files to be renamed, either through the find command or by simply giving a string, as we will see in the next section.
Notice what follows the for loop
ls | grep .txt
, this command is enclosed in two reverse single quotes, and
$(ls | grep .txt)
The enclosed string is executed as a command, and the string result is returned.
File names contain Spaces
We can write the list of files directly to the for loop instead of using a command, such as:
for file in "file1 file2 file3"
do
...
done
You can see that the for loop splits the string by Spaces, so if the file name to be changed contains Spaces, it will break into multiple file names, causing an error.
To solve this problem, we can set IFS (internal field separator) to newline \n so that the for loop retrieves the value of the variable on a line-by-line basis, ensuring that each time it retrieves a full filename.
The command to set the IFS variable needs to precede the for loop:
IFS=$'\n'
for file in `ls`
do
...
done
You can also directly use the while read command to read 1 line at a time to the variable file:
ls | grep "*.txt" | while read file
do
...
done
Use find to get the list of files
In the previous example, we used the ls command to get the list of files. This command only retrieves files from a directory, and it does not filter for multiple conditions.
When it comes to finding files, I have to mention the powerful find command. The command can find files in multiple levels of the directory, and can set such as the creation time, file size, owner and other conditions, especially convenient to find the file flexible.
The combination of the find command to get the list of files and the sed command to modify the file name with regular expressions can accomplish almost any common batch renaming task.
For example, all files greater than 1M and with the suffix txt or jpg will be renamed from es103EN_20170101.txt, image_20170101.jpg to 20170108en, 2017010101-ES109en. jpg
for file in `find . -size +1M -name "*_*.txt" -o -name "*_*.jpg"`
do
newfile=`echo $file | sed 's/\([a-z]\+\)_\([0-9]\+\)./\2-\1./'`
mv $file $newfile
done
More about find command usage, you can refer to https: / / www ofstack. com article / 108198. htm
conclusion