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 ?
    – MelBurslan
    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.
    – RickA
    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
    – RickA
    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
    – RickA
    Feb 29, 2016 at 23:21
  • Perhaps you're wrong about the file format? Because this should just work. Feb 29, 2016 at 23:25
  • Show me the output of ls where the files live perhaps? 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
    – RickA
    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. 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
    – RickA
    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/"
    – MelBurslan
    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'
    – RickA
    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. Dec 26, 2016 at 23:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.