How can I move a file and append a timestamp to its name via cron job? - cron

I have a file CBD_DATA.zip present in a directory: /home/cbd_dev/CBD_DATA.zip. I want to move it to the directory /home/sundaram_srivastava/archives/ as CBD_DATA_{DateTimeStamp}.zip.
I have tried using a cron job:
* * * * * mv /home/cbd_dev/CBD_DATA.zip /home/sundaram_srivastava/archives > /home/sundaram_srivastava/archives/CBD_DATA_`date +\%d\%m\%y`.zip
The problem with the cron job above is that it moves the file as CBD_DATA.zip into another directory with the same name and then it creates another file CBD_DATA_110620.
Now, the file CBD_DATA_110620 is 0 KB. So, in the destination directory, I have two files, CBD_DATA.zip and CBD_DATA_110620, but I want just one and it should not be empty.
What should I change in my cron code?

First, I'd try and figure out the command on its own, without a cron job. What you're doing is something like this (with shortened directory paths for readability):
mv /foo/CBD_DATA.zip /foo/archives > /foo/archives/CBD_DATA_`date +%d%m%y`.zip
This moves the file and then creates a new empty file; there is no output from the mv command, and the redirection has nothing to redirect, so the file with the datestamp is empty.
The second argument for the mv command is the new location itself; if it is a directory, the filename stays the same, but if it is not a directory, it is interpreted as the new name. You don't need any redirection.
mv /foo/CBD_DATA.zip "/foo/archives/CBD_DATA_$(date '+%d%m%y').zip"
I have replaced the deprecated backticks in the command substitution with $(...) and quoted the expansion. Side note: if you can choose the datestamp format, I'd strongly recommend using +%F (or %Y%m%d) instead so it sorts chronologically.
With your paths and escaped for a cron job (do you really want to run this every minute?):
* * * * * mv /home/cbd_dev/CBD_DATA.zip "/home/sundaram_srivastava/archives/CBD_DATA_$(date +\%d\%m\%y).zip"

Related

How to copy multiple files with varying version numbers from one directory to another using bash?

I have a folder /home/user/Document/filepath where I have three files namely file1-1.1.0.txt, file2-1.1.1.txt, file3-1.1.2.txt
and another folder named /home/user/Document/backuppath where I have to move files from /home/user/Document/folderpath which has file1-1.0.0.txt, file2-1.0.1.txt and file3-1.0.2.txt
task is to copy the specific files from folder path to backup path.
To summarize:
the below is the files.txt where I listed the files which has to be copied:
file1-*.txt
file2-*.txt
The below is the move.sh script that execute the movements
for file in `cat files.txt`; do cp "/home/user/Document/folderpath/$file" "/home/user/Documents/backuppath/" ; done
for the above script I am getting the error like
cp: cannot stat '/home/user/Document/folderpath/file1-*.txt': No such file or directory found
cp: cannot stat '/home/user/Document/folderpath/file2-*.txt': No such file or directory found
what I would like to accomplish is that I would like to use the script to copy specific files using * in the place of version numbers., since the version number may vary in the future.
You have wildcard characters in your files.txt. In your cp command, you are using quotes. These quotes prevent the wildcards to be expanded, as you can clearly see from the error message.
One obvious possibility is to not use quotes:
cp /home/user/Document/folderpath/$file /home/user/Documents/backuppath/
Or not use a loop at all:
cp $(<files.txt) /home/user/Documents/backuppath/
However, this would of course break if one line in your files.txt is a filename pattern which contains white spaces. Therefore, I would recommend a second loop over the expanded pattern:
while read file # Puts the next line into 'file'
do
for f in $file # This expands the pattern in 'file'
do
cp "/home/user/Document/folderpath/$f" /home/user/Documents/backuppath
done
done < files.txt

What does an asterisk at the end of a mv command do

So I am going along and moving a bunch of files
mv /source /dest &
mv /source/* /dest/dest/ &
...
...
then I get careless and
mv /source/filena* /dest/dest/ *
OMG! ^c^c^c^c
[No Response from terminal command]
What is actually going on here?
What happens when I put an * (asterisk) at the end of a command instead of an & (ampersand)?
The shell expands the wildcard *. The mv command never sees the wildcard, only the result of the expansion.
The wildcard * expands to the list of files in the current directory in lexicographic order. If the last file is a directory, then all the preceding files (/source.filenafoo, /source/filenabar, /dest/dest, hello) are moved to that subdirectory. If the last file is not a directory, mv complains that “target a.png is not a directory” (or words to that effect).
See What does mv ./* without specifying destination do? for more detailed examples.
An asterisk at the end of a command line is treated the same way as an asterisk anywhere else on the line — it's a wildcard that matches zero or more characters. Specifically, in this instance, the * in mv /source/filena* /dest/dest/ * is replaced by the name of each & every file and folder in your current directory (except those beginning with a dot), and whatever happens to be last in this list is where mv is going to try to put everything.

How to move and number files?

I working with linux, bash.
I have one directory with 100 folders in it, each one named different.
In each of these 100 folders, there is a file called first.bars (so I have 100 files named first.bars). Although all named first.bars, the files are actually slightly different.
I want to get all these files moved to one new folder and rename/number these files so that I know which file comes from which folder. So the first first.bars file must be renamed to 001.bars, the second to 002.bars.. etc.
I have tried the following:
ls -d * >> /home/directorywiththe100folders/list.txt
cat list.txt | while read line;
do cd $line;
mv first.bars /home/newfolder
This does not work because I can't have 100 files, named the same, in one folder. So I only need to know how to rename them. The renaming must be connected to the cat list.txt, because the first line is the folder containing the first file wich is moved and renamed. That file will be called 001.bars.
Try doing this :
$ rename 's/^.*?\./sprintf("%03d.", $c++)/e' *.bar
If you want more information about this command, see this recent response I gave earlier : How do I rename multiple files beginning with a Unix timestamp - imapsync issue
If the rename command is not available,
for d in /home/directorywiththe100folders/*/; do
newfile=$(printf "/home/newfolder/%d.bars" $(( c++ )) )
mv "$d/first.bars" "$newfile"
done

Check number of files in directory and if equal or more than 5 - remove the oldest one

I'm trying to create a cron job to create mysql backups. I would like to be able to first check how many files are there in the directory and if there are 5 or more remove one (the oldest) and create a new mysqldump. I know how to create the mysqldump, but not sure about the condition. I'm planning to store the procedure in the .sh file and trigger that file once a day with the cronjob.
Could someone show the example of what the procedure should look like?
You could wrap the following in a shell script
for file_to_delete in `ls -1ta test* | tail --lines=+6` ; do echo "ENTER_CMD_HERE $file_to_delete" ; done
where
- test is name of file (replace it with path + name of the mysql bkp files)
- replace ENTER_CMD_HERE with say rm

Bash script arguments, require or fill in specific character

I am writing a bash script that will output a .tgz file to a specific directory, /tmp/ by default
I would like to provide an option to override this directory and I have chosen to do so using arguments provided at the command line
while getopts d: option
do
case "${option}" in
d) dir=${OPTARG};;
esac
done
As written, this works but I've run into a snag depending on user input
The name of my .tgz file is also a variable and my code that brings this all together is
output="$dir""$name"
The problem that I run into is if the user runs
./script -d /home/user
My resulting path and filename end up as
/home/userfilename.tgz
I need to either enforce a requirement for a trailing / or insert one if the user did not.
While it works, if I change my output variable to
output="$dir"/"$name"
If the user does provide a trailing / I end up with something like this and I am trying to keep my output aesthetic.
/home/user//filename.tgz
Any input would be greatly appreciated.
Add the line
output="${output//\/\///}"
after joining dir and name.
It looks complicated, but what it does is it replaces two slashes with one.
You may find more info in here.

Resources