Copy Date/Time without actual files? - a real head scratcher
Linux - SoftwareThis forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
Copy Date/Time without actual files? - a real head scratcher
I have a minor problem. I have about 250,000 files that I copied over from another drive and when I did the rsync, I did not copy over the dates and times of the original files. The original drive is now unavailable, but I have a backup from a few weeks ago that will do nicely. However, hundreds of files have been changed because of normal daily use because the problem was not noticed for several days.
I am wondering if it is possible to copy over just the dates and times of the backup files and folders without copying over the actual file data itself? I found a utility called 2xExplorer for windows that has a feature called "sync touch", but it does not work recursively and does not copy the dates and times of the folders. For example, I have a file titled spreadsheet.xls dated 4-03-03 on the backup and on the new drive spreadsheet.xls dated 8-15-06. I just would like to copy over the date and time without touching the data within spreadsheet.xls. Sorry if I sound redundant, but I wanted to make sure I gave out as much information as possible. If anyone out there knows of a way or has an example script (for Windows or Linux, it does not matter), I would be much appreciative. Thanks in advance!
well you can use `find`, just read the man page for it, you can find all files in a directory within a certain time range, then use the -exec flag to apply a command to those files (like some command that overwrites it with the right time)
just be careful, jun some tests without the command to make you sure you have all the syntax right
you also might be able to diff the files and update your archive and then copy everything over again
well you can use `find`, just read the man page for it, you can find all files in a directory within a certain time range, then use the -exec flag to apply a command to those files (like some command that overwrites it with the right time)
just be careful, jun some tests without the command to make you sure you have all the syntax right
you also might be able to diff the files and update your archive and then copy everything over again
I think I see where you're going. Now, I haven't worked it all out, but I assume you mean something along the lines of "find /oldpath/* | touch -m /newpath" or something like that? If I am way off, do you have an example? Thank you in advance.
#!/bin/bash
# Uncomment the line below for debug/errormode
# set -xe
# whoami
progn=${0//*\//}
help() { echo -en "${progn}: -t -s source -d dest -l strip prefix\n\
-t: test on 10 samples\n -s source directory name,\n -d destination \
directory name,\n -l strip number of directory prefixes.\n"; exit 1; }
[ "${progn}" != "touchit.sh" ] && exit 127
[ "$#" -eq "0" ] && help
[ "${1:0:1}" != "=" ] && help
while getopts s:d:l:th OPT; do case "$OPT" in
s) src_dir="${OPTARG}";; d) dst_dir="${OPTARG}";;
l) strip="${OPTARG}";; t) test=1;; h) help;; esac
done
findcmd="find "${src_dir}""; case "$test" in 1) add="|head -10";; esac
$findcmd | while read f; do
expr index "${f}" "\+" > /dev/null && break
time=$(stat -c %y "${f}"); time=${time:0:19}
if [ -n "$strip" ]; then
dst_f=${f// /+}; dst_f=(${dst_f//\// }); elem=${#dst_f[@]}
if [ "$strip" -lt "$elem" ]; then
dst_f="${dst_f[@]:${strip}}"; dst_f="${dst_f// //}"; dst_f="${dst_dir}/${dst_f//+/ }"
fi; else dst_f="${dst_dir}/${f}"; fi
if [ -e "${dst_f}" ]; then
case "$test" in 1) echo "touch -c -d "${time}" "${dst_f}"";;
*) touch -c -d "${time}" "${dst_f}";; esac
fi
done
exit 0
Save as "touchit.sh" and make executable. Say source dir (-s) is "/tmp/backup" and destination (-d) directory to modify is "/home/tbeehler/tmp/backup", now with "-l" you can strip the disparate directory levels:
#!/bin/bash
# Uncomment the line below for debug/errormode
# set -xe
# whoami
progn=${0//*\//}
help() { echo -en "${progn}: -t -s source -d dest -l strip prefix\n\
-t: test on 10 samples\n -s source directory name,\n -d destination \
directory name,\n -l strip number of directory prefixes.\n"; exit 1; }
[ "${progn}" != "touchit.sh" ] && exit 127
[ "$#" -eq "0" ] && help
[ "${1:0:1}" != "=" ] && help
while getopts s:d:l:th OPT; do case "$OPT" in
s) src_dir="${OPTARG}";; d) dst_dir="${OPTARG}";;
l) strip="${OPTARG}";; t) test=1;; h) help;; esac
done
findcmd="find "${src_dir}""; case "$test" in 1) add="|head -10";; esac
$findcmd | while read f; do
expr index "${f}" "\+" > /dev/null && break
time=$(stat -c %y "${f}"); time=${time:0:19}
if [ -n "$strip" ]; then
dst_f=${f// /+}; dst_f=(${dst_f//\// }); elem=${#dst_f[@]}
if [ "$strip" -lt "$elem" ]; then
dst_f="${dst_f[@]:${strip}}"; dst_f="${dst_f// //}"; dst_f="${dst_dir}/${dst_f//+/ }"
fi; else dst_f="${dst_dir}/${f}"; fi
if [ -e "${dst_f}" ]; then
case "$test" in 1) echo "touch -c -d "${time}" "${dst_f}"";;
*) touch -c -d "${time}" "${dst_f}";; esac
fi
done
exit 0
Save as "touchit.sh" and make executable. Say source dir (-s) is "/tmp/backup" and destination (-d) directory to modify is "/home/tbeehler/tmp/backup", now with "-l" you can strip the disparate directory levels:
I'm going to try this out tonight. Thank you VERY much! This code is a bit over my head and I would have banged my head on a desk forever trying to put together something like this. You sir are my personal hero!
you might want to diff the files to make sure you only reset the date on those files that haven't changed.
or maybe do a checksum instead of a diff... perhaps unSpawn's script does something like that, but i haven't read it yet cuz i'm afraid my head might explode...
OK, so now it's both your fault ;-p Here's a version with mandatory choice of verification method (-m: use "md5" or "diff"). BTW, the script doesn't handle any names containing an add sign, I had to unfsck space usage in an array. OK, I could have done some IFS mod, maybe someone else wants to correct it. And this one's untested actually ;-p but then again but i haven't read it yet cuz i'm afraid my head might explode.
it's been de-formatted for your reading pleasure: wouldn't want to loose some valuable fellow LQ members in the process...
Code:
#!/bin/bash
# whoami
progn=${0//*\//}
# uncomment line below to enable debug/errormode
# set -xe
help() { # spit out help text and exit 1
echo -en "${progn}: -t -s source -d dest -l strip prefix\n -t: test on 10 samples\n -s source directory name,\n\
-d destination directory name,\n -l strip number of directory prefixes,\n -m method [md5|diff].\n"; exit 1
}
vrfy() { #verify files
case "$1" in
md5) sum_src=($(md5sum "${f}")); sum_dst=($(md5sum "${dst_f}"));
expr match ${sum_src[0]} ${sum_dst[0]} >/dev/null;;
diff) diff -aqH "${f}" "${dst_f}" >/dev/null;;
*) exit 127;;
esac;
}
# If I'm not called this I won't run.
[ "${progn}" != "touchit.sh" ] && exit 127
# If the first char of the first arg isn't this char I won't run.
[ "${1:0:1}" != "-" ] && echo help
# If the amount of args is zero I spit out a help message (and exit 1)
[ "$#" -eq "0" ] && help
# Preflight check: args
while getopts s:d:l:th OPT; do
case "$OPT" in
s) src_dir="${OPTARG}";;
d) dst_dir="${OPTARG}";;
l) strip="${OPTARG}";;
t) test=1;;
m) method="${OPTARG}";;
h) help;;
esac
done
# Only do testing with say ten files
findcmd="find "${src_dir}""
case "$test" in
1) add="|head -10";;
esac
# By now we got rotation, we're on our way...
$findcmd | while read f; do
# Commence incursion or abort on add sign:
expr index "${f}" "\+" > /dev/null && break
# Get waypoints lined up (modification time string)
time=$(stat -c %y "${f}"); time=${time:0:19}
# Stalinistic guidance systems in place (remove prefix dirs)
if [ -n "$strip" ]; then
# transmogrify spaces into add sign w/o using "echo" and "sed" or "tr"
dst_f=${f// /+};
# transmogrify slashes into spaces w/o using "echo" and "sed" or "tr"
dst_f=(${dst_f//\// });
# If the amount of strip levels doesn't exceed the amount of array elements
if [ "$strip" -lt "${#dst_f[@]}" ]; then
dst_f="${dst_f[@]:${strip}}";
dst_f="${dst_f// //}";
dst_f="${dst_dir}/${dst_f//+/ }"
fi
# If we don't need to remove prefix dirs, then
else
dst_f="${dst_dir}/${f}"
fi
# If target can be aquired, then
if [ -e "${dst_f}" ]; then
# See if we need visual confirmation first
case "$test" in
# Report back results and carry out target EW
1) vrfy $method && echo "touch -c -d "${time}" "${dst_f}"";;
*) vrfy $method && touch -c -d "${time}" "${dst_f}";;
esac;
fi
# Out of targets, return to FOB
done
# End of flight, touch down and don't use ejection seat but exit properly.
exit 0
OK, so now it's both your fault ;-p Here's a version with mandatory choice of verification method (-m: use "md5" or "diff"). BTW, the script doesn't handle any names containing an add sign, I had to unfsck space usage in an array. OK, I could have done some IFS mod, maybe someone else wants to correct it. And this one's untested actually ;-p but then again but i haven't read it yet cuz i'm afraid my head might explode.
it's been de-formatted for your reading pleasure: wouldn't want to loose some valuable fellow LQ members in the process...
Code:
#!/bin/bash
# whoami
progn=${0//*\//}
# uncomment line below to enable debug/errormode
# set -xe
help() { # spit out help text and exit 1
echo -en "${progn}: -t -s source -d dest -l strip prefix\n -t: test on 10 samples\n -s source directory name,\n\
-d destination directory name,\n -l strip number of directory prefixes,\n -m method [md5|diff].\n"; exit 1
}
vrfy() { #verify files
case "$1" in
md5) sum_src=($(md5sum "${f}")); sum_dst=($(md5sum "${dst_f}"));
expr match ${sum_src[0]} ${sum_dst[0]} >/dev/null;;
diff) diff -aqH "${f}" "${dst_f}" >/dev/null;;
*) exit 127;;
esac;
}
# If I'm not called this I won't run.
[ "${progn}" != "touchit.sh" ] && exit 127
# If the first char of the first arg isn't this char I won't run.
[ "${1:0:1}" != "-" ] && echo help
# If the amount of args is zero I spit out a help message (and exit 1)
[ "$#" -eq "0" ] && help
# Preflight check: args
while getopts s:d:l:th OPT; do
case "$OPT" in
s) src_dir="${OPTARG}";;
d) dst_dir="${OPTARG}";;
l) strip="${OPTARG}";;
t) test=1;;
m) method="${OPTARG}";;
h) help;;
esac
done
# Only do testing with say ten files
findcmd="find "${src_dir}""
case "$test" in
1) add="|head -10";;
esac
# By now we got rotation, we're on our way...
$findcmd | while read f; do
# Commence incursion or abort on add sign:
expr index "${f}" "\+" > /dev/null && break
# Get waypoints lined up (modification time string)
time=$(stat -c %y "${f}"); time=${time:0:19}
# Stalinistic guidance systems in place (remove prefix dirs)
if [ -n "$strip" ]; then
# transmogrify spaces into add sign w/o using "echo" and "sed" or "tr"
dst_f=${f// /+};
# transmogrify slashes into spaces w/o using "echo" and "sed" or "tr"
dst_f=(${dst_f//\// });
# If the amount of strip levels doesn't exceed the amount of array elements
if [ "$strip" -lt "${#dst_f[@]}" ]; then
dst_f="${dst_f[@]:${strip}}";
dst_f="${dst_f// //}";
dst_f="${dst_dir}/${dst_f//+/ }"
fi
# If we don't need to remove prefix dirs, then
else
dst_f="${dst_dir}/${f}"
fi
# If target can be aquired, then
if [ -e "${dst_f}" ]; then
# See if we need visual confirmation first
case "$test" in
# Report back results and carry out target EW
1) vrfy $method && echo "touch -c -d "${time}" "${dst_f}"";;
*) vrfy $method && touch -c -d "${time}" "${dst_f}";;
esac;
fi
# Out of targets, return to FOB
done
# End of flight, touch down and don't use ejection seat but exit properly.
exit 0
Any speedups and corrections welcome as usual.
Ok, perhaps I'm an idiot, let's get that out of the way. But when I run the script, I get bash: ./touchit.sh: /bin/bash^M: bad interpreter: No such file or directory. My syntax that I am using is ./touchit.sh -t -s /home/testing -d /home/testing.new -l 3 I looked around and I do have a /bin/bash I've looked through the script to see if it was looking for anything else, but my scripting isn't of this level. Do you have any suggestions? I appreciate your help VERY much.
Ok, perhaps I'm an idiot, let's get that out of the way. But when I run the script, I get bash: ./touchit.sh: /bin/bash^M: bad interpreter: No such file or directory. My syntax that I am using is ./touchit.sh -t -s /home/testing -d /home/testing.new -l 3 I looked around and I do have a /bin/bash I've looked through the script to see if it was looking for anything else, but my scripting isn't of this level. Do you have any suggestions? I appreciate your help VERY much.
Hi,
you'll have to get those CRs out there. LF only at the end of line.
OK, so now it's both your fault ;-p Here's a version with mandatory choice of verification method (-m: use "md5" or "diff"). BTW, the script doesn't handle any names containing an add sign, I had to unfsck space usage in an array. OK, I could have done some IFS mod, maybe someone else wants to correct it. And this one's untested actually ;-p but then again but i haven't read it yet cuz i'm afraid my head might explode.
it's been de-formatted for your reading pleasure: wouldn't want to loose some valuable fellow LQ members in the process...
Code:
#!/bin/bash
# whoami
progn=${0//*\//}
# uncomment line below to enable debug/errormode
# set -xe
help() { # spit out help text and exit 1
echo -en "${progn}: -t -s source -d dest -l strip prefix\n -t: test on 10 samples\n -s source directory name,\n\
-d destination directory name,\n -l strip number of directory prefixes,\n -m method [md5|diff].\n"; exit 1
}
vrfy() { #verify files
case "$1" in
md5) sum_src=($(md5sum "${f}")); sum_dst=($(md5sum "${dst_f}"));
expr match ${sum_src[0]} ${sum_dst[0]} >/dev/null;;
diff) diff -aqH "${f}" "${dst_f}" >/dev/null;;
*) exit 127;;
esac;
}
# If I'm not called this I won't run.
[ "${progn}" != "touchit.sh" ] && exit 127
# If the first char of the first arg isn't this char I won't run.
[ "${1:0:1}" != "-" ] && echo help
# If the amount of args is zero I spit out a help message (and exit 1)
[ "$#" -eq "0" ] && help
# Preflight check: args
while getopts s:d:l:th OPT; do
case "$OPT" in
s) src_dir="${OPTARG}";;
d) dst_dir="${OPTARG}";;
l) strip="${OPTARG}";;
t) test=1;;
m) method="${OPTARG}";;
h) help;;
esac
done
# Only do testing with say ten files
findcmd="find "${src_dir}""
case "$test" in
1) add="|head -10";;
esac
# By now we got rotation, we're on our way...
$findcmd | while read f; do
# Commence incursion or abort on add sign:
expr index "${f}" "\+" > /dev/null && break
# Get waypoints lined up (modification time string)
time=$(stat -c %y "${f}"); time=${time:0:19}
# Stalinistic guidance systems in place (remove prefix dirs)
if [ -n "$strip" ]; then
# transmogrify spaces into add sign w/o using "echo" and "sed" or "tr"
dst_f=${f// /+};
# transmogrify slashes into spaces w/o using "echo" and "sed" or "tr"
dst_f=(${dst_f//\// });
# If the amount of strip levels doesn't exceed the amount of array elements
if [ "$strip" -lt "${#dst_f[@]}" ]; then
dst_f="${dst_f[@]:${strip}}";
dst_f="${dst_f// //}";
dst_f="${dst_dir}/${dst_f//+/ }"
fi
# If we don't need to remove prefix dirs, then
else
dst_f="${dst_dir}/${f}"
fi
# If target can be aquired, then
if [ -e "${dst_f}" ]; then
# See if we need visual confirmation first
case "$test" in
# Report back results and carry out target EW
1) vrfy $method && echo "touch -c -d "${time}" "${dst_f}"";;
*) vrfy $method && touch -c -d "${time}" "${dst_f}";;
esac;
fi
# Out of targets, return to FOB
done
# End of flight, touch down and don't use ejection seat but exit properly.
exit 0
Any speedups and corrections welcome as usual.
Ok so I got the CR/LF issue resolved, but I run the script (both versions) and neither work? The first script gives me the standard touchit.sh: -t -s source -d dest -l strip prefix, etc, etc, while the new script just give me the next line like it worked if I don't put in the -m, but if I go and check the dates, they are still incorrect. I tried the new one with the -m option but it tells me that -m is an illegal option regardless of where I put the -m (before or after source or destination, etc)I apologize for being a pest, and I really appreciate all the help you guys have given me. Thanks in advance!
You see, "-m" switch requires an argument. If that doesn't work run as
Code:
sh -x ./touchit.sh -t -m md5 -s /tmp/backup -d /home/tbeehler/tmp/backup -l 3 2>&1 | tee ./touchit.tee
and post the first say ten lines of ./touchit.tee.
Well I finally got a free moment today and got time to run your code. Hopefully this helps you out. Thank you for all your help. I truly appreciate it! I tried the -m option with diff and md5 options and got no where. On my machine I ran: sh -x ./touchit.sh -t -m md5 -s /home/tbeehler/Desktop/old/ -d /home/tbeehler/Desktop/new/ -l 3 2>&1 | tee ./touchit.tee and got:
+ progn=touchit.sh
+ '[' touchit.sh '!=' touchit.sh ']'
+ '[' - '!=' - ']'
+ '[' 9 -eq 0 ']'
+ getopts s:d:l:th OPT
+ case "$OPT" in
+ test=1
+ getopts s:d:l:th OPT
./touchit.sh: illegal option -- m
+ case "$OPT" in
+ getopts s:d:l:th OPT
+ findcmd='find '
+ case "$test" in
+ add='|head -10'
+ find
+ read f
+ expr index . '\+'
++ stat -c %y .
+ time='2006-09-12 15:28:02.000000000 -0400'
+ time='2006-09-12 15:28:02'
+ '[' -n '' ']'
+ dst_f=/.
+ '[' -e /. ']'
+ case "$test" in
+ vrfy
+ case "$1" in
+ exit 127
+ exit 0
./touchit.sh: illegal option -- m
+ case "$OPT" in
+ getopts s:d:l:th OPT
OK. Just add "m:".
Change the line "while getopts s:d:l:th OPT; do"
to read: "while getopts s:d:l:m:th OPT; do"
sh -x ./touchit.sh -t -m md5 -s /home/tbeehler/Desktop/old/ -d /home/tbeehler/Desktop/new/ -l 3 2>&1 | tee ./touchit.tee
BTW, try switch "-l 4" instead of 3. You'll why see if you use debug mode ("sh -x") like you already did.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.