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


Related articles: