1

I have files in the format YYYY_MM_DD_HH:MM:SS.swf that dump into a folder /home/user/dump/

I want to move these files into a new directory tree /home/user/save/year/month/day/ based on the YYYY_MM_DD from the filename. Alternatively, if these can be modified by the file modification date, that is acceptable as well. I've found a couple other scripts on here, but they don't seem to have all the info I'm looking for.

3
  • what did you do so far ? What is failing ? Commented Feb 29, 2016 at 21:33
  • I've tried this script on the first response, but it spits out an error on line 21. I'm not sure if it would output the /year/month/day/ structure. Commented Feb 29, 2016 at 21:38
  • All files hold this same pattern. No, no directories should be ignored. Hopefully the format is something like 2016/02/29 Commented Feb 29, 2016 at 23:15

4 Answers 4

3

If you have the Perl-based rename (sometimes known as prename) you can do this with a single command:

cd /home/user/dump rename -v 'use File::Path qw(make_path); m!^((....)_(..)_(..)_(.*))!; my $d = "$2/$3/$4"; make_path($d); s!^!$d/!' * 

Actually this is a fairly ugly (mis)use of rename. For each file, the code runs as follows

  1. Include a system library that allows for directory path creation
  2. Match against the YYYY_MM_DD structure at the beginning of the filename
  3. Create the corresponding directory path YYYY/MM/DD (if necessary)
  4. Move (rename) the file into its YYYY/MM/DD directory, leaving its name unchanged
2

Zsh

Use the zmv function to move or rename files matched by a wildcard expression. There's no built-in way to create the destination directory, so I provide a function to do it.

autoload -U zmv mkdir_mv () { mkdir -p -- ${(P)#:h} mv -- $@ } cd /home/user/dump zmv -p mkdir_mv '(????)_(??)_(??)_??:??:??.swf' '/home/user/save/$1/$2/$3/$f' 

POSIX shell

If you need a portable solution, use a shell loop over the files, and shell string manipulation to extract the parts of the file names.

cd /home/user/dump for f in ????_??_??_??:??:??.swf; do year=${f%%_*}; suffix=${f#*_} month=${suffix%%_*}; suffix=${suffix#*_} day=${suffix%%_*} mkdir -p "/home/user/save/$year/$month/$day" mv "$f" "/home/user/save/$year/$month/$day/$f" done 
0
while read file do f=$(basename $file) year=$(echo "$f"|cut -f1 -d_) day=$(echo "$f"|cut -f3 -d_) month=$(echo "$f"|cut -f2 -d_) new_dir="/home/user/save/$year/$month/$day" mkdir -p "$new_dir" mv "$file" "$new_dir" done < <(find /home/user/dump -type f -name "*_*_*_*:*:*.swf") 
15
  • I ran this script, and it created /home/user/dump/home/user/save/2016/02/file.swf -- it is missing the day folder. I might be missing something here but this is close Commented Feb 29, 2016 at 23:21
  • Perhaps you're wrong about the file format? Because this should just work. Commented Feb 29, 2016 at 23:25
  • Show me the output of ls where the files live perhaps? Commented Feb 29, 2016 at 23:26
  • This is actually very close. 'for file in $(find /home/user/dump/ -name "*.swf") do year=$(echo ${file}|cut -d_ -f1) month=$(echo ${file}|cut -d_ -f2) day=$(echo ${file}|cut -d_ -f3) if [ ! -d /home/user/dump_save/${year}/${month}/${day} ] then mkdir -p /home/user/dump_save/${year}/${month}/${day} fi mv ${file} /home/user/dump_save/${year}/${month}/${day} done ' This duplicates the directory, though and creates 'user/dump_save/home/user/dump/2016/02/day' where the day is working correctly. ls of where the files lives /home/user/dump/2016_02_26_06:51:40.swf Commented Feb 29, 2016 at 23:33
  • It shouldn't, that isn't what the code says to do, are you editing the code? How are you running it? Both answers given to you were correct as far as I can see, so my instinct is that you are leaving out info, or doing something incorrectly. Commented Feb 29, 2016 at 23:35
0
for file in $(find /home/user/dump/ -name "*.swf") do year=$(echo ${file}|cut -d_ -f1) month=$(echo ${file}|cut -d_ -f2) day=$(echo ${file}|cut -d_ -f3) if [ ! -d /home/user/save/${year}/${month}/${day} ] then mkdir -p /home/user/save/${year}/${month}/${day} fi mv ${file} /home/user/save/${year}/${month}/${day} done 
4
  • This is close - it moves the files, but 'doubles' the directory tree, i.e. saves the files in /home/user/save/home/user/save/year/month. Also, it omits the 'Day' folder Commented Feb 29, 2016 at 23:06
  • Then your file name format is not what you presented it to be, i.e. YYYY_MM_DD_HH:MM:SS.swf. Please post a section of the output from `ls -l /home/user/dump/" Commented Feb 29, 2016 at 23:18
  • File format example '"/home/user/dump/2016_02_26_06:51:40.swf"' or '2016_02_27_09:57:14.swf' Commented Feb 29, 2016 at 23:27
  • Note that this would choke on file names containing spaces and other special characters. Also using pipes to cut to process strings is rather slow. Commented Dec 26, 2016 at 23:46

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.