In Bash, how can I access the date of when a file was last edited? - linux

Basically, I can see that
ls -l
displays the date that all the files in a directory were last edited. What I want to do is to access the date and then store it into a variable using a .sh script. However, not exactly sure what I can do to do so, and I've looked up the man pages for ls as well as searched up the matter to no avail.

If your date command supports the -r option, you can use it:
variable=$(date -r file)
The advantage of the date command is that you'll be able to format the date in many ways. For example, in seconds since Epoch:
variable=$(date -r file +%s)

Use stat with the correct format option:
stat -c%y file

Related

How to automate calling of a file that is created daily with date stamp in file name

I used logrotate to create a log file that gets rolled over every day at 03:00; so the file that is created has the following format:
userlog.%Y-%m-%d
the script then zips the file as well so the end result is userlog.%Y-%m-%d.gz .... an actual file name is userlog.2015-09-09.gz.
I am writing a shell script that will copy the file created every day and will then unzip it, run a search on the log, extract results, format them, and then email them, and then delete the copied zip file.
I can get everything to work smoothly but I cannot copy the file using the method that it was created in.
I am trying to run the following:
sudo cp userlog.%Y-%d-%m.gz /home/local/temp
but the command does not execute. My understanding is that the current date, month, and year should be substituted into the variable fields in the file name.
If you could please correct my approach and understanding of this concept. Or please let me know if you feel this should work. Or if there is an alternate approach to call a file created in this fashion then kindly advise.
Presently I am having to write the filename into the script manually every morning and I would very much like to escape this hardship.
You need a simple command substitution.
sudo cp userlog.$(date +%Y-%d-%m).gz /home/local/temp
%Y by itself is just a static string; but when passed as an argument to the date command, it specifies the four-digit year for the given date. (Default is today's date.)
Regardless of your problems with this particular command, you should certainly not need to edit the script file every day. A very fundamental feature of scripts is the parametrization of arguments. If your current script looks like
#!/bin/bash
gzgrep -c "failure" /path/to/userlog.2015-09-11.gz
sudo cp /path/to/userlog.2015-09-11.gz /home/local/temp
then it can easily be refactored to read the date as a command-line parameter:
#!/bin/bash
: ${1?"Syntax: $0 yyyy-mm-dd"}
gzgrep -c "failure" /path/to/userlog."$1".gz
sudo cp /path/to/userlog."$1".gz /home/local/temp
If you saved this as userlog somewhere in your PATH, the solution to your original problem would now be simply
userlog $(date +%Y-%m-%d)
which of course could be saved as a script, too, or as a shell function in your personal .bash_profile or similar. But if this is mandatory daily routine, you'll probably prefer to add it as a cron job to run every morning (even if you are away). Cron will send you an email with any output. (Do notice that cron does not necessarily have the same PATH etc as your interactive login shell, though.)

Can you hide the 'date modified' time of a folder on a linux system?

Is it possible to hide the 'date modified' attribute of a folder that I 'own' on a Linux system?
I know I can change permissions on the folder, but for a specific security reason, I'd like to also make the date/time of the last modification to the folder hidden to other users. Is this possible? Any tips or workarounds are appreciated :D
You can change the modification time of a file using the touch command:
touch filename
By default this will set the file's modification time to the current time, but there are a number of flags, such as the -d flag to pick a particular date. So for example, to set a file as being modified two hours before the present, you could use the following:
touch -d "2 hours ago" filename
If you want to modify the file relative to its existing modification time instead, the following should do the trick:
touch -d "$(date -r filename) - 2 hours" filename
If you want to modify a large number of files, you could use the following:
find DIRECTORY -print | while read filename; do
# do whatever you want with the file
touch -d "$(date -r "$filename") - 2 hours" "$filename"
done
You can change the arguments to find to select only the files you are interested in. If you only want to update the file modification times relative to the present time, you can simplify this to:
find DIRECTORY -exec touch -d "2 hours ago" {} +
This form isn't possible with the file time relative version because it uses the shell to form the arguments to touch.
As far as the creation time goes, most Linux file systems do not keep track of this value. There is a ctime associated with files, but it tracks when the file metadata was last changed. If the file never has its permissions changed, it might happen to hold the creation time, but this is a coincidence. Explicitly changing the file modification time counts as a metadata change, so will also have the side effect of updating the ctime.

How do I rename multiple files beginning with a Unix timestamp - imapsync issue

I didn't got the script from imapsync to rename maildir filenames to work. :-/
So what I need is:
I have a mail folder with thousands of mails. After importing those emails to my new server, the filename of the emails got the creation date as a Unix timestamp in the filename, but the creation date flag of the file is the correct receive date from the email.
ls -l for one file looks like this:
-rw-r--r-- 1 popuser popuser 1350432 2013-03-16 07:22 1363563215.M562903P29332V0000000000000802I0000000000AEA46B_527.my-domain.org,S=1350432:2,S
So what the script has to do is:
1) read the creation date/time of the file (I found the command
stat -c %y filename
does this)
2) convert the date/time from 1) to a Unix timestamp
date -d "2013-03-17 11:19:01.000000000 +0100" "+%s"
3) delete the first 10 digits (wrong timestamp) of the filename and us the the timestamp from 2) instead
4) do this for all files in a specific directory
I'm a newby in Linux scripts, can anyone help me with this script?
Thank you!
Try doing this with rename :
$ rename -n 's/^\d+/(stat($_))[9]/e' [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*
from the shell prompt. It's very useful, you can put some perl code like I does in a substitution for stat with the e modifier.
You can remove the -n (dry-run mode switch) when your tests become valids.
There are other tools with the same name which may or may not be able to do this, so be careful.
If you run the following command (linux)
$ file $(readlink -f $(type -p rename))
and you have a result like
.../rename: Perl script, ASCII text executable
and not containing:
ELF
then this seems to be the right tool =)
If not, to make it the default (usually already the case) on Debian and derivative like Ubuntu :
$ sudo update-alternatives --set rename /path/to/rename
(replace /path/to/rename to the path of your perl's rename command.
If you don't have this command, search your package manager to install it or do it manually
Last but not least, this tool was originally written by Larry Wall, the Perl's dad.
Edit
As stated here, if you have the following error :
Argument list too long
Then use find like this :
find -type f -name '[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]*' -print0|
xargs -0 -n1 rename -n 's/^\d+/(stat($_))[9]/e'
(try it without -n1, that should works too)

Update file, but not alter file modify date. Can it be done?

In Linux, can i change file content, but keep the same modification date of that file? If yes, then how? Thanks.
Get what is the modification Date of your file.
Change your files content and then you can change the modification date by touch command.For example
touch -m -t 09082000 file
to change the modification time to 8 sep, 20:00.
You can change the modification date to the past too, for 10/15/1998 12:30 the command would be something like this:
touch -m -t 19981015123000 file
another possibility might be a symbolic link?
if you have alink->a.txt, you change the content of a.txt, the last modi time of alink won't be updated.
You can memorize the modification date before modifying the content; After the content modification, you can modify back the date to the initial value. It can be done in Linux from the command line. For example:
touch -t 09082000 file
to change the modification time to 8 sep, 20:00. More info can be found here.
As I had a similar problem now and found this question via google, I'll give an easy, automatic solution. I store the current modification time in the variable CURRENT, then after modifying the file, I set the modification time back to its original time via touch. Please note that getting the timestamp for current is a bit clumsy, you might need to modify it a bit.
FILE=test.txt
touch $FILE
CURRENT=$(date -r $FILE +%Y%m%d%H%M)
# run your command here
touch $FILE
touch -a -m -t $CURRENT $FILE

Adding timestamp to a filename with mv in BASH

Well, I'm a linux newbie, and I'm having an issue with a simple bash script.
I've got a program that adds to a log file while it's running. Over time that log file gets huge. I'd like to create a startup script which will rename and move the log file before each run, effectively creating separate log files for each run of the program. Here's what I've got so far:
pastebin
DATE=$(date +"%Y%m%d%H%M")
mv server.log logs/$DATE.log
echo program
When run, I see this:
: command not found
program
When I cd to the logs directory and run dir, I see this:
201111211437\r.log\r
What's going on? I'm assuming there's some syntax issue I'm missing, but I can't seem to figure it out.
UPDATE: Thanks to shellter's comment below, I've found the problem to be due to the fact that I'm editing the .sh file in Notepad++ in windows, and then sending via ftp to the server, where I run the file via ssh. After running dos2unix on the file, it works.
New question: How can I save the file correctly in the first place, to avoid having to perform this fix every time I resend the file?
mv server.log logs/$(date -d "today" +"%Y%m%d%H%M").log
The few lines you posted from your script look okay to me. It's probably something a bit deeper.
You need to find which line is giving you this error. Add set -xv to the top of your script. This will print out the line number and the command that's being executed to STDERR. This will help you identify where in your script you're getting this particular error.
BTW, do you have a shebang at the top of your script? When I see something like this, I normally expect its an issue with the Shebang. For example, if you had #! /bin/bash on top, but your bash interpreter is located in /usr/bin/bash, you'll see this error.
EDIT
New question: How can I save the file correctly in the first place, to avoid having to perform this fix every time I resend the file?
Two ways:
Select the Edit->EOL Conversion->Unix Format menu item when you edit a file. Once it has the correct line endings, Notepad++ will keep them.
To make sure all new files have the correct line endings, go to the Settings->Preferences menu item, and pull up the Preferences dialog box. Select the New Document/Default Directory tab. Under New Document and Format, select the Unix radio button. Click the Close button.
A single line method within bash works like this.
[some out put] >$(date "+%Y.%m.%d-%H.%M.%S").ver
will create a file with a timestamp name with ver extension.
A working file listing snap shot to a date stamp file name as follows can show it working.
find . -type f -exec ls -la {} \; | cut -d ' ' -f 6- >$(date "+%Y.%m.%d-%H.%M.%S").ver
Of course
cat somefile.log > $(date "+%Y.%m.%d-%H.%M.%S").ver
or even simpler
ls > $(date "+%Y.%m.%d-%H.%M.%S").ver
I use this command for simple rotate a file:
mv output.log `date +%F`-output.log
In local folder I have 2019-09-25-output.log
Well, it's not a direct answer to your question, but there's a tool in GNU/Linux whose job is to rotate log files on regular basis, keeping old ones zipped up to a certain limit. It's logrotate
You can write your scripts in notepad but just make sure you convert them
using this ->
$ sed -i 's/\r$//' yourscripthere
I use it all they time when I'm working in cygwin and it works. Hope this helps
First, thanks for the answers above! They lead to my solution.
I added this alias to my .bashrc file:
alias now='date +%Y-%m-%d-%H.%M.%S'
Now when I want to put a time stamp on a file such as a build log I can do this:
mvn clean install | tee build-$(now).log
and I get a file name like:
build-2021-02-04-03.12.12.log

Resources