3 #=======================================================================
5 # File ID: d4b6028a-5d36-11df-8bab-90e6ba3022ac
6 # Reads file names from stdin or files and places them into a directory
7 # structure based on a date in the file name or the modification time.
10 # ©opyleft 2004– Øyvind A. Holm <sunny@sunbase.org>
11 # License: GNU General Public License, see end of file for legal stuff.
12 #=======================================================================
22 our ($opt_c, $opt_d, $opt_h, $opt_l, $opt_L, $opt_m, $opt_o, $opt_q) =
23 ( 0, "", 0, 0, 0, 0, 0, 0);
24 our ($opt_s, $opt_S, $opt_v) =
26 getopts
('cd:hlLmoqsSv') || die("Option error. Use -h for help.\n");
31 $progname =~ s
#^.*/(.*?)$#$1#;
33 my $DEFAULT_DIR = "%Y/%m/%d";
34 my $skip_dirs = $opt_s ?
1 : 0;
35 my $skip_files = ($opt_s | $opt_S) ?
1 : 0;
37 my $simul_str = $skip_files ?
" (simulating)" : "";
41 if ($opt_c + $opt_l + $opt_L > 1) {
42 die("$0: Can’t mix the \"-c\", \"-l\" or \"-L\" options, " .
43 "only one or none allowed.\n");
51 if ($opt_l && ($_ !~ /^\//)) {
52 warn("$_: Pathname is not absolute\n");
56 if (/^(.*)\/([^\
/]+?)$/) {
64 if ($opt_m || $File =~ /^(.*?)\b(\d\d\d\d)-?(\d\d)-?(\d\d)T(\d\d):?(\d\d):?(\d\d)Z\b(.+)/) {
66 my ($Pre, $Year, $Mon, $Day, $Hour, $Min, $Sec, $Rest);
68 ($Pre, $Year, $Mon, $Day, $Hour, $Min, $Sec, $Rest) =
69 ( $1, $2, $3, $4, $5, $6, $7, $8);
71 my $From = "$Path/$File";
76 my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev,
77 $size, $atime, $mtime, $ctime, $blksize, $blocks) =
79 my @TA = gmtime($mtime);
80 ( $Year, $Mon, $Day, $Hour, $Min, $Sec) =
81 ($TA[5]+1900, $TA[4]+1, $TA[3], $TA[2], $TA[1], $TA[0]);
82 $Year = sprintf("%04u", $Year);
83 $Mon = sprintf("%02u", $Mon);
84 $Day = sprintf("%02u", $Day);
85 $Hour = sprintf("%02u", $Hour);
86 $Min = sprintf("%02u", $Min);
87 $Sec = sprintf("%02u", $Sec);
90 my $Dir = length($opt_d) ?
$opt_d : $DEFAULT_DIR;
99 my $Dest = "$Dir/$File";
101 if (!$opt_o && -e
$Dest) {
102 $opt_q || warn("$Dest: File already exists, will not overwrite\n");
107 mkpath
($Dir, $opt_v ?
1 : 0, 0777) ||
108 die("mkpath(\"$Dir\", 0, 0777): $!");
111 print("Copying \"$From\" to " .
112 "\"$Dest\"$simul_str...");
114 copy
($From, $Dest) ||
115 die("\ncopy(\"$From\", \"$Dest\"): $!");
116 $opt_v && print("OK\n");
119 print("Linking \"$From\" to " .
120 "\"$Dest\"$simul_str...");
122 link($From, $Dest) ||
123 die("\nlink(\"$From\", \"$Dest\"): $!");
124 $opt_v && print("OK\n");
127 print("Symlinking \"$From\" to " .
128 "\"$Dest\"$simul_str...");
130 symlink($From, $Dest) ||
131 die("\nsymlink(\"$From\", " .
133 $opt_v && print("OK\n");
136 print("Moving \"$From\" to " .
137 "\"$Dest\"$simul_str...");
139 move
($From, $Dest) ||
140 die("\nmove(\"$From\", \"$Dest\"): $!");
141 $opt_v && print("OK\n");
147 $opt_q || warn("Ignoring non-regular file $From\n");
150 warn("$From: File not found\n");
157 # Send the help message to stdout {{{
164 Syntax: $0 [options] [file_with_filenames [...]]
166 The program reads file names from stdin or from the files on the command
167 line and moves or copies the files into a directory structure defined by
168 the user. It can also create soft or hard links if the file system
169 allows it. The file name has to contain a date on the format
173 which is the date specified in UTC.
177 -c Copy files instead of move
178 -d X Place files under directory X
179 Use the following modifiers for subtree layout:
181 %Y Year with four digits
183 %d Day of month (00..31)
187 %% Regular percent sign
189 If the -d option is not specified, "$DEFAULT_DIR" will be used.
192 -l Create symlinks instead of moving or copying files. The file names
193 in the input has to contain an absolute path to prevent creating
194 dead links. File names not starting with "/" will be ignored.
195 -L Create hard links to the files instead of copying or moving.
196 -m Use the file modification time instead of date found in the file
197 name. All files will be affected, not only those with a date in
199 -o Overwrite existing files
200 -q Be quiet, suppress non-critical messages.
201 -s Simulate, don't really move or copy files.
202 -S Semisimulate. Don’t touch the files, only create the directory
203 structure. Useful for running tests with big amounts of data.
206 These options are likely to change at the moment.
208 Note: Files on the command line will not be moved themselves, but shall
209 contain file names of the relevant files to be moved.
214 find /var/tmp/afvroot | afv_move -vl -d newdir/%Y-%m-%d/%H
215 afv_move -vL /tmp/filenames.txt -d %Y/%Y-%m-%d
217 Made by Øyvind A. Holm <sunny\@sunbase.org>
218 License: GNU General Public License version 2 or later ♥
231 This program is free software; you can redistribute it and/or modify it
232 under the terms of the GNU General Public License as published by the
233 Free Software Foundation; either version 2 of the License, or (at your
234 option) any later version.
236 This program is distributed in the hope that it will be useful, but
237 WITHOUT ANY WARRANTY; without even the implied warranty of
238 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
239 See the GNU General Public License for more details.
241 You should have received a copy of the GNU General Public License along
242 with this program; if not, write to the Free Software Foundation, Inc.,
243 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
247 # vim: set fenc=UTF-8 ft=perl fdm=marker ts=4 sw=4 sts=4 et fo+=w :
248 # End of file afv_move