简体   繁体   中英

Renaming multiple files in one line of shell

Problem

In a directory there are files of the format: *-foo-bar.txt.

Example directory:

$ ls *-*
asdf-foo-bar.txt  ghjk-foo-bar.txt  l-foo-bar.txt     tyui-foo-bar.txt
bnm-foo-bar.txt   iop-foo-bar.txt   qwer-foo-bar.txt  zxcv-foo-bar.txt

Desired directory:

$ ls *.txt
asdf.txt  bnm.txt  ghjk.txt  iop.txt  l.txt  qwer.txt  tyui.txt  zxcv.txt

Solution 1

The first solution that came to my mind looks somewhat like this ugly hack:

ls *-* | cut -d- -f1 | sed 's/.*/mv "\0-foo-bar.txt" "\0.txt"/' > rename.sh && sh rename.sh

The above solution creates a script, on the fly, to rename the files. This solution also tries to parse the output of ls which is not a good thing to do as per http://mywiki.wooledge.org/ParsingLs .

Solution 2

This problem can be solved more elegantly with a shell script like this:

for i in *-*
do
    mv "$i" "`echo $i | cut -f1 -d-`.txt"
done

The above solution uses a loop to rename the files.

Question

Is there a way to solve this problem in a single line such that we do not have to explicitly script a loop, or generate a script, or invoke a new or the current shell (ie avoid sh, bash, ., etc. commands)?

Have you tried the rename command?

For example:

rename 's/-foo-bar//' *-foo-bar.txt

If you don't have that available, I would use find , sed , and xargs :

find . -maxdepth 1 -mindepth 1 -type f -name '*-foo-bar.txt' | sed 's/-foo-bar.txt//' | xargs -I{} mv {}-foo-bar.txt {}.txt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM