I'm trying to check if a directory if existing file, if so then I would like to remove the file before moving new file in that directory.
if [[${abc_directory}/filename*.dmp]] ; then
rm -rf ${abc_directory}/filename*.dmp
I think I am missing some logic in the if statement.
Simply do:
rm -f "${abc_directory}"/filename*.dmp
The option -f (--force) tells rm to ignore non existing files.
I have not included -r, because following your description, you will remove single files and not directory trees.
I have escaped the ${abc_directory} part to avoid issues with spaces. It assumes, that abc_directory doesn't contain any wanted wildcards/placeholders.
You're not looking for a specific file in your example, you're using a wild card. Why not just do a rm -rf ${abc_directory}/filename*.dmp before moving in the new file and be done with it?
Here's how to check for existence of a single file.
if [ -e ${abc_directory}/filename.dmp ];then
rm -f ${abc_directory}/filename.dmp
fi
Related
I have a txt file with a list of files (approximately 500) for example:
file_0_hard.msOut
file_1_hard.msOut
file_10_hard.msOut
.
.
.
file_1000_hard.msOut
I want to delete all those files whose name is not in the txt file. All of these files are in the same directory. How can I do this using bash where I read the text file and then delete all those files in the directory that are not in the text file. Help would be appreciated.
Along the lines of user1934428
There is something to say for this solution. But since we have linux at our disposal with a strong filesystem in use I hope. we can make hardlinks; The only requirement for that the destination is on the same filesystem.
So along those lines:
make a directory to store the files you want to keep.
hardlink (ln {file} {target}) ; as this does not cost extra disk space, it only stores the inode number in the new directory file.
remove all files
move the files back from their origin.
And actually this would be about the same as:
mv {files} {save spot}
remove all files
mv {save spot}/{files} back
Which does pretty much the same thing. Then again; it is a nice way to learn about the power of a hardlink.
you may try this :
cd path/dir
for f in *; do
if ! grep -Fxq "$f" pathToFile/file.txt; then
rm -r "$f"
else
printf "exists-- %s \n" ${f}
fi
done
In case you are wondering (as I did) what -Fxq means in plain English:
F: Affects how PATTERN is interpreted (fixed string instead of a regex)
x: Match whole line
q: Shhhhh... minimal printing
Assuming the directory in question is mydir
set -e
cd mydir
tmpdir=/tmp/x$$ # adapt this to your taste
mv $(<list.txt) $tmpdir
cd ..
rm -r mydir
mkdir mydir
mv $tmpdir/* mydir
rm -r $tmpdir
Basically, instead to delete those files you want to keep, you safe them, then delete everything, and then restore them. For your case, this is probably faster than doing the other way around.
UPDATE:
As Michiel commented, it is advisable that you place your tmpdir in the same file system as mydir.
I have a few files with the format ReportsBackup-20140309-04-00 and I would like to send the files with same pattern to the files as the example to the 201403 file.
I can already create the files based on the filename; I would just like to move the files based on the name to their correct folder.
I use this to create the directories
old="directory where are the files" &&
year_month=`ls ${old} | cut -c 15-20`&&
for i in ${year_month}; do
if [ ! -d ${old}/$i ]
then
mkdir ${old}/$i
fi
done
you can use find
find /path/to/files -name "*201403*" -exec mv {} /path/to/destination/ \;
Here’s how I’d do it. It’s a little verbose, but hopefully it’s clear what the program is doing:
#!/bin/bash
SRCDIR=~/tmp
DSTDIR=~/backups
for bkfile in $SRCDIR/ReportsBackup*; do
# Get just the filename, and read the year/month variable
filename=$(basename $bkfile)
yearmonth=${filename:14:6}
# Create the folder for storing this year/month combination. The '-p' flag
# means that:
# 1) We create $DSTDIR if it doesn't already exist (this flag actually
# creates all intermediate directories).
# 2) If the folder already exists, continue silently.
mkdir -p $DSTDIR/$yearmonth
# Then we move the report backup to the directory. The '.' at the end of the
# mv command means that we keep the original filename
mv $bkfile $DSTDIR/$yearmonth/.
done
A few changes I’ve made to your original script:
I’m not trying to parse the output of ls. This is generally not a good idea. Parsing ls will make it difficult to get the individual files, which you need for copying them to their new directory.
I’ve simplified your if ... mkdir line: the -p flag is useful for “create this folder if it doesn’t exist, or carry on”.
I’ve slightly changed the slicing command which gets the year/month string from the filename.
I have a problem. I have files with extension .war in /root/tmp/despliegue/webapps, I want remove directories with the same name without extension in /usr/share/tomcat6/webapps
I have obteined the names without suffix with:
for entry in /root/tmp/despliegue/webapps/* ; do basename $entry .war ; done
I need remove with the output previous loop... someone like this.
for entry in /root/tmp/despligue/webapps/* ; do rm -rf /usr/share/tomcat6/webapps`basename $entry .war`; done
Thank you guys.
Sorry for my very bad English.
You only want to loop over files that have the .war extension, so you should use *.war instead of *:
for entry in /root/tmp/despligue/webapps/*.war; do
rm -rf "/usr/share/tomcat6/$(basename "$entry" .war)"
done
Your question says that you have the .war files in /root/tmp/despliegue/, but your code says they are stored in /root/tmp/despliegue/webapps/. Also the questions says the directories are in /usr/share/tomcat6/webapps/, however your code uses /usr/share/tomcat6/.
You can use bash wildcard globing to list only files ending in .war and then do parameter expansion with ${variable%.*} which removes the shortest matching suffix (i.e. removes everything from the last period on and returns what's left)
for entry in /root/tmp/despligue/webapps/*.war; do [[ -f $entry && -d "${entry%.*}" ]] && rm -rf "${entry%.*}"; done
Note, the above also checks:
That $entry is a regular file (not a symlink or dir); and
That ${entry%.*} is a valid directory before trying to remove it.
I'm trying to make a simple script that copies all of my $HOME into another folder in $HOME called Backup/. This includes all hidden files and folders, and excludes Backup/ itself. What I have right now for the copying part is the following:
shopt -s dotglob
for file in $HOME/*
do
cp -r $file $HOME/Backup/
done
Bash tells me that it cannot copy Backup/ into itself. However, when I check the contents of $HOME/Backup/ I see that $HOME/Backup/Backup/ exists.
The copy of Backup/ in itself is useless. How can I get bash to copy over all the folders except Backup/. I tried using extglob and using cp -r $HOME/!(Backup)/ but it didn't copy over the hidden files that I need.
try rsync. you can exclude file/directories .
this is a good reference
http://www.maclife.com/article/columns/terminal_101_using_rsync_locally
Hugo,
A script like this is good, but you could try this:
cp -r * Backup/;
cp -r .* Backup/;
Another tool used with backups is tar. This compresses your backup to save disk space.
Also note, the * does not cover . hidden files.
I agree that using rsync would be a better solution, but there is an easy way to skip a directory in bash:
for file in "$HOME/"*
do
[[ $file = $HOME/Backup ]] && continue
cp -r "$file" "$HOME/Backup/"
done
This doesn't answer your question directly (the other answers already did that), but try cp -ua when you want to use cp to make a backup. This recurses directories, copies rather than follows links, preserves permissions and only copies a file if it is newer than the copy at the destination.
I am trying to write a bash script that does the following:
Enumerates through list of files in a directory, that match a specified pattern
Creates a tar file containing the matching files
Removes (i.e. deletes) the matched files from their source directories
To keep things simple, I intend to use a hard coded list of directories and file patterns
This is what I have come up with so far:
#!/bin/bash
filenames[0]='/home/user1/*.foo'
filenames[1]='/some/otherpath/*.fbar'
for f in ${filenames[#]}
do
echo "$f"
done
However, I am unusure on how to proceed from this point onward. Specifically, I need help on:
How to glob the files matching the pattern $f
How to add the ENTIRE list of matching files (i.e. from all directories) to a tar file in one go
Regarding deleting the files, I am thinking of simply iterating through the ENTIRE list obtained in step 2 above, and 'rm' the actual file - is there a better/quicker/more elegant way?
PS:
I am running this on Ubuntu 10.0.4 LTS
If you want to use a loop because you have many directories, you can use the -r option to append to the tar file. You can also use --remove-files to remove files after adding them to the archive.
filenames[0]='/home/user1/*.foo'
filenames[1]='/some/otherpath/*.fbar'
for f in "${filenames[#]}"
do
tar -rvf --remove-files foo.tar $f
done
If you don't have the --remove-files option, use rm $f after the tar command.
tar(1) supports an --remove-files option that will remove the files after adding them to the archive.
Depending upon what you're trying to do with your shell globs, you might be able to ignore doing all that extra work there, too. Try this:
tar cf /dir/archive.tar --remove-files /home/user1/*.foo /some/otherpath/*.fbar