Why does ''rm "$dir"/* !(.gitignore)'' delete the script itself? - bash

I have this shell script that I'm using to clean up some temp files.
The script is stored in: /root/cronjobs.
When I run the script from this location ./cleanUploader.sh, it deletes all the files in the current folder along with itself.
Here's the script:
#!/bin/bash
# cleanUploader.sh
# Batch file to remove various temp directories and files left over from the Uploader
clear
echo
INHOUSEFILES=/var/www/html/inhouseweb/officedb/uploader/files
shopt -s extglob
if [ -d $INHOUSEFILES ]; then
echo "Removing directory $INHOUSEFILES"
rm -rf $INHOUSEFILES/* !(".gitignore")
else
echo "directory $INHOUSEFILES not found"
fi
echo
shopt -u extglob
echo
echo "Done"
What am I doing wrong?

rm -rf $INHOUSEFILES/* !(".gitignore")
This deletes all files in $INHOUSEFILES/*, and then it also deletes everything in the current directory except .gitignore. That's what !(".gitignore") does when it's a separate argument.
If your intention is to delete everything in $INHOUSEFILES/ except .gitignore then combine the two arguments:
rm -rf $INHOUSEFILES/!(".gitignore")
It's also a good idea to quote variable expansions. (And conversely you don't need them around a literal string like .gitignore.)
rm -rf "$INHOUSEFILES"/!(.gitignore)

Related

Use of mkdir -v output with a newline embedded

First of all, this question is purely theoric; it involves creates a directory with a newline, thing that should NEVER be done.
That said, I'm trying to use mkdir -pv output to remove the created directories in a specific moment of my script, but only the newly created, not the ones that previously existed.
Command mkdir -pv will print one line per directory not-existent before this command call so that I can re-inject in a rm -rf command. It works OK except in the case that directory contains a newline, and I can't see what is wrong with it.
My minimal working example:
declare -a created
# Delete previous traces
mkdir_out=$(mkdir -pv 'new 10'{1,2,3,$'\n',"'a",4})
# Convert to array
IFS=$'\n' read -d '' -a created < <(printf '%s' "${mkdir_out}")
# Debug
printf '=>[1] %s\n' "${created[#]}"
# We only want content between first and last quote
created=( "${created[#]%[\'\"]}" )
created=( "${created[#]#*[\'\"]}" )
# Debug
printf '=>[2] %s\n' "${created[#]}"
rm -rfv "${created[#]}"
ls # Directory "new 10\n" is still there!!
So, what is the safe way to do that?
Output like mkdir: created directory 'foo' is only meant for humans. Don't try to parse it.
If you want to handle all possible filenames and you can't deal in \0 separated lists, you have to do them one by one. Here's an example:
declare -a created dirs
dirs=( 'new 10'{1,2,3,$'\n',"'a",4} )
created=()
for dir in "${dirs[#]}"
do
if [[ ! -d "$dir" ]] && mkdir -p "$dir"
then
created+=( "$dir" )
fi
done
rm -rfv "${created[#]}"
ls # Directory "new 10\n" is not there.

rm: cannot remove '–rf': No such file or directory

I have a Bash script that automates creating some SVN folders. In the course of doing so, it creates a temporary directory. When I try to delete that temp directory with the rm -rf command, I get the following error...
rm: cannot remove '–rf': No such file or directory
It seems to think that "-rf" is a file name. The command works fine on the command line.
Here is my script...
#!/bin/bash
if [ $# -lt 1 ]; then
echo "Usage: $0 reponame1 reponame2 ..."
else
for var in "$#"
do
REPONAME=$var
mkdir -p ~/temp-$REPONAME/branches
mkdir ~/temp-$REPONAME/tags
mkdir ~/temp-$REPONAME/trunk
svnadmin create $REPONAME
svn import ~/temp-$REPONAME svn+ssh://username#192.168.123.234/home/username/svnrepos/$REPONAME -m "Initial structure"
rm –rf ~/temp-$REPONAME/
done
fi
And here is the output
$ ./mkrepo.sh mysvnrepo
username#192.168.123.234's password:
username#192.168.123.234's password:
Adding /home/username/temp-mysvnrepo/branches
Adding /home/username/temp-mysvnrepo/tags
Adding /home/username/temp-mysvnrepo/trunk
Committing transaction...
Committed revision 1.
rm: cannot remove '–rf': No such file or directory
rm: cannot remove '/home/username/temp-mysvnrepo/': Is a directory
You managed to type a unicode "EN DASH"(U+2013) which is not recognised by rm as a normal hyphen "-"(U+002D) so rm thinks it is the beginning of a file name and not of your parameters. They do look alike, but they are not the same for a program. To fix it, just erase it and type it again making sure you take the normal hyphen/minus key.
The '-' in your script in rm –rf is not the one it expects.
The correct one is rm -rf.
I hope you can spot the difference.
rm –rf
rm -rf

Can't iterate correctly over specific files in folder with endings {*-enterprise.ipa,*.apk}

I have a folder containing these app files:
mles:fairs-ionic mles$ ls build
build/com.solutions.enterprise.fairs.dev_v2.2.0.17_20170720_1423-enterprise.ipa
build/com.solutions.enterprise.fairs_v2.2.0.17_20170720_1423-enterprise.ipa
build/de.fairs.dev_v2.2.0.17_20170720_1423-enterprise.apk
build/de.fairs_v2.2.0.17_20170720_1423-appstore.ipa
build/de.fairs_v2.2.0.17_20170720_1423-enterprise.apk
I need to uppload all of them except the *-appstore.ipa one. More specifically these one:
mles:fairs-ionic mles$ ls build/{*-enterprise.ipa,*.apk}
build/com.solutions.enterprise.fairs.dev_v2.2.0.17_20170720_1423-enterprise.ipa
build/com.solutions.enterprise.fairs_v2.2.0.17_20170720_1423-enterprise.ipa
build/de.fairs.dev_v2.2.0.17_20170720_1423-enterprise.apk
build/de.fairs_v2.2.0.17_20170720_1423-enterprise.apk
In my bash script I've tried:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
appFiles=($(cd ${DIR}/build;ls {*-enterprise.ipa,*.apk}))
echo ${appFiles};
echo "loop"
for appFile in "${appFiles[#]}"
do
echo ${appfile}
#app_upload "${appfile}"
done
this yields:
mles:fairs-ionic ben$ ./test.sh
com.solutions.enterprise.fairs.dev_v2.2.0.17_20170720_1423-enterprise.ipa
loop
appFiles only contains one row, and the appfile variable in the loop is always empty.
How can I iterate over all the files in the build folder except the .ipa files with appstore in the filename (build/de.fairs_v2.2.0.17_20170720_1423-appstore.ipa) ?
Variable appfile is not defined only appFile, So change
echo ${appfile}
to
echo ${appFile}
Edit the line displaying all the data
echo ${appFiles};
To
echo ${appFiles[*]};
You can just do this simply with extended glob features (see Options which change globbing behavior) provided by bash, turn the options on and stash the values to an array. Run it outside the build/ folder.
shopt -s extglob nullglob
fileList=( build/!(*-appstore.ipa) )
now loop over the array and do whatever you want to do with it.
for file in "${fileList[#]}"; do
printf "%s\n" "$file"
done
You don't need to create an array of selected files as you can directly iterate them using a glob with brace expansion like this:
for file in build/*{-enterprise.ipa,.apk}; do
echo "$file"
# app_upload "$file"
done

Bash to search and delete?

I need a script that will search for a file in a applications directory and delete it. If it's not there it will continue with the install.
What I'm needing deleted:
/Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png
If that's not found I want it to continue on the install. If it finds that file I want it to delete it before continuing the installation.
This is what I've got:
#!/bin/bash
file="/Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png"
if [ -f "$file" ]
then
echo "$file delteling old icon"
rm -rf /Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png
else
echo "$file old icon deleted already moving on"
fi
try this
#!/bin/bash
if [ -e <your_file> ]; then
rm -f <your_file>
fi
this should do.
Parentheses are used to start a subshell in bash, so you'll need to put your filename in double-quotes (as you did in the file test).
Change the line:
rm -rf /Applications/Cydia.app/Sections/Messages(D3#TH's-Repo).png
To:
rm -rf "${file}"
And this will remove the file (assuming no permissions problems).

Delete a directory only if it exists using a shell script

I have a shell (ksh) script. I want to determine whether a certain directory is present in /tmp, and if it is present then I have to delete it. My script is:
test
#!/usr/bin/ksh
# what should I write here?
if [[ -f /tmp/dir.lock ]]; then
echo "Removing Lock"
rm -rf /tmp/dir.lock
fi
How can I proceed? I'm not getting the wanted result: the directory is not removed when I execute the script and I'm not getting Removing Lock output on my screen.
I checked manually and the lock file is present in the location.
The lock file is created with set MUTEX_LOCK "/tmp/dir.lock" by a TCL program.
In addition to -f versus -d note that [[ ]] is not POSIX, while [ ] is. Any string or path you use more than once should be in a variable to avoid typing errors, especially when you use rm -rf which deletes with extreme prejudice. The most portable solution would be
DIR=/tmp/dir.lock
if [ -d "$DIR" ]; then
printf '%s\n' "Removing Lock ($DIR)"
rm -rf "$DIR"
fi
For directory check, you should use -d:
if [[ -d /tmp/dir.lock ]]; then
echo "Removing Lock"
rm -rf /tmp/dir.lock
fi

Resources