2

I have a directory tree where the path elements correspond to specific properties of the file at a particular path. For example, something like this:

$ tree 
. ─ a ─ 1 ─ y ─ 334f
│   │   └── z ─ 6410
│   └── 2 ─ y ─ e776
└── b ─ 1 ─ y ─ 9828
    └── 2 ─ y ─ 0149
        └── z ─ 563a

I want to change the order of the path elements to put the (x|y) part first, then (1|2), then (a|b). (For example, ./a/1/y/334f should become ./y/1/a/334f.)

The complete final tree should be:

$ tree
. ─ y ─ 1 ─ a ─ 334f
│   │   └── b ─ 9828
│   └── 2 ─ a ─ e776
│       └── b ─ 0149
└── z ─ 1 ─ a ─ 6410
    └── 2 ─ b ─ 563a

How do I do this?

Jeff Schaller
  • 66,199
  • 35
  • 114
  • 250
AJMansfield
  • 834
  • 1
  • 10
  • 20
  • Since 'tree' is a representation of the directory structure it wont do what you want unless you want to `mv` all the files and then redraw the tree. Is that what you want? Or are you actually looking to draw an abstract tree based upon a set of relationships? Using the path elements as you would use fields in a database? – bu5hman Nov 21 '17 at 18:15
  • @bu5hman I'm looking to either move all the files, or (if it's simpler) create a new tree full of symbolic links to the original files. – AJMansfield Nov 21 '17 at 18:34
  • Similar to https://unix.stackexchange.com/a/266623/100397 – roaima Nov 21 '17 at 23:48

1 Answers1

3

Create the target directories:

for d in */*/*;do mkdir -p $(echo $d | sed -r 's:(.+)/(.+)/(.+):\3/\2/\1/:'); done

Move the files:

for d in */*/*;do mv $d/* $(echo $d | sed -r 's:(.+)/(.+)/(.+):\3/\2/\1/:'); done

(this version wil complain that there are no files in the directories created in step #1, you can improve on the */*/* or create the target directories elsewhere)

xenoid
  • 8,648
  • 1
  • 24
  • 47
  • Why not store the path? `for oldPath in */*/*; do newPath=$(sed -r 's:(.+)/(.+)/(.+):\3/\2/\1/:' <<< $oldPath) ; mkdir -p $newPath; mv $oldPath/* $newPath; done` – bu5hman Nov 22 '17 at 04:24
  • @bu5hman I a script I would have done so, but when trying things on a command line I prefer self-standing one-liners. – xenoid Nov 22 '17 at 07:26
  • A matter of taste, but whenever I do a bulk `mv` or `rm` I like to make a dry run and check the output by `echo` ing it first. Experience (read this as 'screaming and banging my head against the wall after losing / overwriting data') has led me to exercise a little caution. Even with apparently 'harmless' one-liners...... :-( – bu5hman Nov 22 '17 at 14:39