Home > Net >  How to split the string with delimiter and swap the substring's position in bash?
How to split the string with delimiter and swap the substring's position in bash?

Time:11-03

This is the scenario,

For example, we have a list of files named as a.txt,b.txt,...z.txt. Goal is to name them as txt.a,txt.b,txt.c.....txt.z

Input:

a.txt
b.txt
c.txt
...
...
z.txt

Output:

txt.a
txt.b
txt.c
...
...
txt.z

I tried this one-liner and got the desired output. One-liner

ls -l *.txt | awk -F " " '{print $9}' | awk -F "." '{str1 = $2; str2 = "."; str3 = $1; str4 = str1 str2 str3; print str4}'

Ask: Could someone help if there is still any better way in bash to achieve this functionality?

CodePudding user response:

If the filename is the last column, and the files have a single dot, you can use a single awk to split on a dot and print the 2 parts in reverse.

Using $NF matches the last field.

ls -l *.txt | awk '
{
    split($NF, a, ".")
    print a[2] "." a[1]
}'

If there should be 2 parts after the split, you can check the result from split:

ls -l *.txt | awk '
{
    n=split($NF, a, ".")
    if (n == 2) print a[2] "." a[1]
}'

Or as an alternative using sed and 2 capture groups printed in reverse, using ls -1 to list one file per line.

ls -1 *.txt | sed -E 's/^([^.] )\.([^.]*)$/\2\.\1/'

CodePudding user response:

Assumptions/understanding:

  • the objective is to rename the files (the question mentions Goal is to name them as ... but there is no mention of the mv command ... ???)
  • all file names contain a single period
  • we want to switch the before-period/after-period portions of the file names to create new file names
  • no files exist with the new file name (eg, we don't currently have files named a.txt and txt.a)

One idea using parameter expansion which allows us to eliminate the overhead of sub-process calls:

for fname in *.txt
do
    new_fname="${fname#*.}.${fname%.*}"
    echo mv "${fname}" "${new_fname}"
done

For files names a.txt, b.txt and c.txt this generates:

mv a.txt txt.a
mv b.txt txt.b
mv c.txt txt.c

Once OP is satisfied with the results the echo can be removed and the script should perform the actual mv/rename.

  • Related