1

I'm trying to rename several directories adding dashes after fourth and sixth characters. I looked at this post How do I loop through only directories in bash? and was able to successfully loop through the directories that I wish to insert the dashes into. However, after seeing this Rename files add dashes after fourth and sixth characters I though perhaps I could use similar syntax on directories, but after doing so realized it can't be done that way. This was my syntax:

for d in */ ; do
      mv “$d" “${d::4}-${d:4:2}-${d:6}"
done

I searched through SE and didn't see another post like this. I apologize in advance if this question is answered elsewhere.

Also, thank you in advance for any help you might offer. Best, Jon

Jon
  • 13
  • Looks like it should work: d=abcdefghijkl; echo "${d::4}-${d:4:2}-${d:6}" gives abcd-ef-ghijkl. Though you have some curly quotes there, and they won't work right in the shell. Make sure to change them to ASCII quotes. The renaming loop looks fine. (Though you might want to use mv -n to prevent trashing any files that happen to exist under the new names) – ilkkachu Dec 19 '22 at 20:51

2 Answers2

1

Using Perl's rename to rename all of your directories:

rename -n 's/^(.{4})(.{2})/${1}-${2}-/' */

Remove -n when your tests are satisfactory.

Ex:

$ mkdir foobarbase{a..c}
$ rename -n 's/(.{4}) # 1st capture group
               (.{2}) # 2nd capture group
              /${1}-${2}-/x' foobar*
rename(foobarbasea, foob-ar-basea)
rename(foobarbaseb, foob-ar-baseb)
rename(foobarbasec, foob-ar-basec)

If you want to keep your code, replace by ascii double quote: "

  • 1
    +1. perl rename is the right answer, but I'd use . rather than \w...the OP didn't say their file/dir names only had locale-specific "word"-characters (from man perlre: "alphanumeric plus "_", plus other connector punctuation chars plus Unicode marks") – cas Dec 20 '22 at 03:04
0

i change character to " :

for d in */ ; do
      mv "$d" "${d::4}-${d:4:2}-${d:6}"
done

my directory's

#ls
fooobar1   fooobar2  fooobar4  fooobar6  fooobar8
fooobar10  fooobar3  fooobar5  fooobar7  fooobar9

and after run

#ls
fooo-ba-r10  fooo-ba-r3  fooo-ba-r5  fooo-ba-r7  fooo-ba-r9
fooo-ba-r1  fooo-ba-r2   fooo-ba-r4  fooo-ba-r6  fooo-ba-r8

your code change name for all directory and file, but if you only change directory name's use this code:
find * -maxdepth 0 -type d  | while read d
do
      mv "$d" "${d::4}-${d:4:2}-${d:6}"
done
read @ilkkachu comment
Baba
  • 3,279
  • 1
    no, the glob */ only matches directories due to the trailing slash. That find | while read would fail for filenames with newlines, backslashes or leading spaces (at least). Instead, you should rather use find ... -exec sh -c 'd=$1; mv "$d" "${d::4}-${d:4:2}-${d:6}"' sh {} \; – ilkkachu Dec 19 '22 at 21:03
  • @Baba That was it! Just a typo on my part. Many thanks! – Jon Dec 19 '22 at 21:34