The rename
utility in Ubuntu can rename directory structures but it won't clean up after itself.
rename 's#(.+)/(.+)/(.+)#$1-$2-$3#' */*/*/
Stick -vn
on the end if you just want it to tell you what it's going to do before it renames anything, but here's a little test harness that shows you what's possible:
$ mkdir -p 2014/06/15
$ touch 2014/06/15/photo_{001..003}.jpg
$ tree
.
└── 2014
└── 06
└── 15
├── photo_001.jpg
├── photo_002.jpg
└── photo_003.jpg
$ rename 's#(.+)/(.+)/(.+)#$1-$2-$3#' */*/*/
$ tree
.
├── 2014
│ └── 06
└── 2014-06-15
├── photo_001.jpg
├── photo_002.jpg
└── photo_003.jpg
Simply put it's being fed the third-level directories and renaming is reading the earlier two segments and renaming it, sticking it in the current directory. As you can see there will be a load of year directories. Assuming they're empty you could clean up with something like (and I pray you check they're empty first):
find -maxdepth 1 -type d -regex '\./[0-9][0-9][0-9][0-9]' -exec rm -irf "{}" \;
I'm using the -i option to force it to ask you before deleting every file. Remove that at your own risk.
Try sed
with the following regex:
$ sed -i.bak 's_\(.*\),[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
Here we have used the sed
's group substitution method to get the desired output.
\(.*\)
will match upto blah, blah, blah
as we have ,[[:blank:]]
to match ,
after it.
\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)
will match the remaining portion of the line (the portion we want to put at the start).
Then we have \2 \1
to put the second group at first and then then a space and then the first group.
The original file will be backed up as file.txt.bak
, if you don't want that use just -i
instead of -i.bak
.
**Although you will get the desired output, using Regex/sed will not be the optimum solution in this case.
EDIT: If you have a line like [Internet disconnected] Friday, Mar 13,2015 15:48:34
, try this:
$ sed -i.bak 's_\(.*[^,]\),*[[:blank:]]\([[:alpha:]]\+,[[:blank:]][[:alpha:]]\+[[:blank:]][[:digit:]]\+,[^,]\+$\)_\2 \1_' file.txt
Friday, Mar 13,2015 15:48:34 [Internet disconnected]
Friday, Mar 13,2015 16:59:42 blah, blah, blah
Friday, Mar 13,2015 16:51:11 yadi, yadi, yada
In the previous regex we had \(.*\),[[:blank:]]
(a comma and a whitespace after the first matching group), now to include the new line in the output we have made the first matching group \(.*[^,]\)
to ensure that it does not end with a comma and then we have matched ,*
i.e. one or more commas. So, the new sed
command will work for all mentioned cases.
Best Answer
Assuming you have access to perl
rename
(generally available in Ubuntu - thanks to @Serg for clarifying the difference. If in doubt, call/usr/bin/rename
and you should get the right one), you could use:Remove
-n
after testing to actually rename the directories. This assumes all the albums date between 1000 and 9999. Probably reasonable...Explanation
s/old/new
replaceold
withnew
(.*)
save any number of any characters to reference as$1
later(\d{4})\/
save four digits at the end of the line to reference as$2
later.*/
match all directories (not files - thanks to @muru for help!)