Shell script to check whether the entered file name is a hidden file or not in RadHat Linux - linux

How do i create a script to check for the file is hidden or not?
#!/bin/bash
FILE="$1"
if [ -f "$FILE" ];
then
echo "File $FILE is not hidden."
else
echo "File $FILE is hidden" >&2
fi
but it is unable to do so. Please help me.

Check if the filename begins with .:
file=$1
base=$(basename "$file")
if [[ $base == .* ]]
then echo "File $file is hidden"
else echo "File $file is not hidden"
fi

You essentially have to check if filename starts with . (period).
filename=$(basename -- "$FILE")
Then you have to use pattern matching
if [[ $filename == .* ]]
then
# do something
fi

The test command would be:
[[ "${file##*/}" == .* ]]
It's necessary to remove the path, to see if file name starts with .. Here I used prefix removal. It's the most efficient, but will choke if a file contains slashes (very unlikely, but be aware).
A full script should include a test that the given file actually exists:
#!/bin/bash
file=$1
[[ -e "$file" ]] && { echo "File does not exist: $file" >&2; exit 1; }
if [[ "${file##*/}" == .* ]]; then
echo "Hidden: $file"
else
echo "Not hidden: $file"
fi
You could also list all hidden files in a directory:
find "$dir" -name .\*
Or all not hidden files:
find "$dir" -name '[^.]*'
Depending on the task, it's probably better to use a list of hidden or not hidden files, to work on.
Also, by default, ls does not list hidden files. Unless you use -a.

Related

Executing different commands with separate arguments

Say that I want to make a script that extracts all tar.gz and tar.bz2 files that are listed as arguments. What I've done so far is something like:
if [[ $# =~ .*"tar.gz".* ]] || [[ $# =~ .*"tar.bz2".* ]]; then
for i in $# =~ .*"tar.gz".*; do
tar -xvzf "$i"
done
for p in $# =~ .*"tar.bz2".*; do
tar -xvjf "$p"
done
else
echo "tar.gz or tar.bz2 files required."
fi
The first line is successful at evaluating whether or not a tar.gz or tar.bz2 file exist, but my problem is the rest. The variables aren't set properly, and the script ends up trying to extract each variable listed with both extraction commands. How can I separate arguments that end with tar.gz and tar.bz2 to perform separate extractions?
You should probably iterate over arguments and test each argument, like this :
#!/bin/bash
declare -i count
for file in "$#"
do
if
[[ $file =~ .*[.]tar[.]gz$ ]]
then
tar -xvzf "$file"
elif
[[ $file =~ .*[.]tar[.]bz2$ ]]
then
tar -xvjf "$file"
else
continue
fi
count+=1
fi
((count)) || echo "tar.gz or tar.bz2 files required."
If you are OK to rely on GNU tar choosing the right decoding algorithm automatically, you can simplify this to :
#!/bin/bash
declare -i count
for file in "$#"
do
[[ $file =~ .*[.]tar[.](gz|bz2)$ ]] || continue
tar -xvf "$file"
count+=1
fi
((count)) || echo "tar.gz or tar.bz2 files required."
There isn't any built-in syntax for extracting and iterating over only matching elements of an array, as you're trying to do here.
The below is POSIX-compliant, depending on no bashisms:
count=0
for arg; do
case $arg in
*.tar.gz) tar -xvzf "$arg"; count=$(( count + 1 ));;
*.tar.bz2) tar -xjvf "$arg"; count=$(( count + 1 ));;
esac
done
if [ "$count" -eq 0 ]; then
echo "tar.gz or tar.bz2 files required" >&2
fi
A bit off-topic, when extracting with GNU tar it detects the archive type automatically from the file extension since 2007, no need to specify z|j|J.
I.e. tar xvf <filename>.

restoring a file to their original location from a log file with paths

I have made 1 script to move user specified files to the dustbin and create a log file with their original paths. Now I want to create a script that the user would only have to input the name of the file to restore it to where it was before and I cannot figure that out.
Here is the code so far:
delete script:
#!/bin/sh
#checks if the user has entered anything.
#if not displays message.
if [ $# -eq 0 ]; then #reads the number of characters
echo "Usage: del <pathname>" >&2
exit 2;
fi
#location of the dustbin
dustbin="$HOME/dustbin"
paths="$HOME/Paths"
if [[ ! -d $dustbin ]]; then #checks if the dustbin exists
mkdir $dustbin
else
[[ -p $dustbin ]] #if dustbin exists does nothing
fi
#creates a Paths folder to store the original location of file(s)
if [[ ! -d $paths ]]; then #checks if the Paths folder exists
mkdir $paths
else
[[ -p $paths ]] #if Paths folder exists does nothing
fi
#gets just the file name
for file in "$#"; do #reads all the arguments
if [[ -e $file ]]; then #checks if the file name exists
#moves the file(s) to the dustbin and writes the orginal file path to the paths.txt file.
find $file >> $HOME/Paths/paths.txt && mv "$file" "$dustbin"
echo "Deleting file(s) $file"
else
echo "The file $file doesn't exist."
fi
done
restore script:
With this I need to search for the file in the dustbin, match the file name to the paths text file that has the files original path and move to the said path.
#!/bin/sh
#checks if the user has entered anything.
#if not displays message.
if [ $# -eq 0 ]; then
echo "Usage: restore <File name>" >&2
exit 2;
fi
#checks if the file paths.txt exist
paths="$HOME/Paths/paths.txt"
if [[ ! -f $paths ]]; then #checks if the Paths file exists
echo "The log file paths.txt doesn't exist. Nothing to restore"
fi
#takes the user input checks if the dustbin exists.
for file in "$#"; do
if [[ ! -d dustbin ]]; then
echo "dustbin doesn't exist"
else
cd $HOME/dustbin
fi
#looks for the user specified file.
if [[ ! -e $file ]]; then
echo "File $file doesn't exist"
else
#restores the file to the original location
restore="grep -n '$file' $paths" #no idea how to do it
mv $file $restore
fi
done
this part I have no idea how to do. I need it to read the user input in $file from the paths.txt and use that stored path to move the $file from the dustbin to the file path stored in the paths.txt file.
#restores the file to the original location
restore="grep -n '$file' $paths" #no idea how to do it
mv $file $restore
So, I think you will want to move the file back to where it originally was using mv.
mv "dustbinPath/$file" "orginalPath/$file"
This will move it from the dustbin path to the originalPath.
EDIT:
If you want to grep the path file for it, you can set a variable to the output of a command like:
originalPath=$(grep 'what_to_grep' file_to_grep.txt)
After you do that that use it in the mv above appropriately (whether the text file contains that file name or not) to move it out.
You can read more about setting a variable to the output from a command here. You might have problems if there are multiple lines that have it however.
In the del script I changed find to realpath so it looks like this:
#gets just the file name
for file in "$#"; do #reads all the arguments
if [[ -e $file ]]; then #checks if the file name exists
realpath $file >> $HOME/Paths/paths.txt && mv "$file" "$dustbin"
echo "Deleting file 'basename $file'"
else
echo "The file $file doesn't exist."
fi
done
and the restore script I added a new variable
rest="$(grep -e $file $paths)" #looking in to the paths.txt file for filename match
#looks for the user specified file in the dustbin.
if [[ ! -e $dustbin/$file ]]; then
echo "File $file doesn't exist"
elif [[ -e $rest ]]; then #if the $file exists in the original path adds an extension .bak
mv $dustbin/$file $rest.bak
else
mv $dustbin/$file $rest #restores the file to the original location
echo "$file restored"
fi

Check that two file exists in UNIX Directory

Good Morning,
I am trying to write a korn shell script to look inside a directory that contains loads of files and check that each file also exists with .orig on the end.
For example if a file inside the directory is called 'mercury_1' there must also be a file called 'mercury_1.orig'
If there isn't, it needs to move the mercury_1 file to another location. However if the .orig file exists do nothing and move onto the next file.
I am sure it is really simple but I am not that experienced in writing Linux scripts and help would be greatly appreciated!!
Here's a small ksh snippet to check if a file exists in the current directory
fname=mercury_1
if [ -f $fname ]
then
echo "file exists"
else
echo "file doesn't exit"
fi
Edit:
The updated script that does the said functionality
#/usr/bin/ksh
if [ ! $# -eq 1 ]
then
echo "provide dir"
exit
fi
dir=$1
cd $dir
#process file names not ending with orig
for fname in `ls | grep -v ".orig$"`
do
echo processing file $fname
if [ -d $fname ] #skip directory
then
continue
fi
if [ -f "$fname.orig" ] #if equiv. orig file present
then
echo "file exist"
continue
else
echo "moving"
mv $fname /tmp
fi
done
Hope its of help!
You can use the below script
script.sh :
#!/bin/sh
if [ ! $# -eq 2 ]; then
echo "error";
exit;
fi
for File in $1/*
do
Tfile=${File%%.*}
if [ ! -f $Tfile.orig ]; then
echo "$File"
mv $File $2/
fi
done
Usage:
./script.sh <search directory> <destination dir if file not present>
Here, for each file with extension stripped check if "*.orig" is present, if not then move file to different directory, else do nothing.
Extension is stripped because you don't want to repeat the same steps for *.orig files.
I tested this on OSX (basically mv should not differ to much from linux). My test directory is zbar and destination is /tmp directory
#!/bin/bash
FILES=zbar
cd $FILES
array=$(ls -p |grep -v "/") # we search for file without extension so put them in array and ignore directory
echo $array
for f in $array #loop in array and find .orig file
do
#echo $f
if [ -e "$f.orig" ]
then
echo "found $f.orig"
else
mv -f "$f" "/tmp"
fi
done

Symlink check - Linux Bash Script

I'm trying to create a script that searches through a directory to find symlinks that point to non-existing objects.
I have a file in a directory with a deleted symlink, but for some reason when i run the below script It says file exists.
#!/bin/bash
ls -l $1 |
if [ -d $1 ]
then
while read file
do
if test -e $1
then
echo "file exists"
else
echo "file does not exist"
fi
done
else
echo "No directory given"
fi
Thanks
Check this page. It has a test for broken links. It uses the -h operator to identify a symlink and the -e operator to check existance.
From that page:
linkchk () {
for element in $1/*; do
[ -h "$element" -a ! -e "$element" ] && echo \"$element\"
[ -d "$element" ] && linkchk $element
# Of course, '-h' tests for symbolic link, '-d' for directory.
done
}
# Send each arg that was passed to the script to the linkchk() function
#+ if it is a valid directoy. If not, then print the error message
#+ and usage info.
##################
for directory in $directorys; do
if [ -d $directory ]
then linkchk $directory
else
echo "$directory is not a directory"
echo "Usage: $0 dir1 dir2 ..."
fi
done
exit $?
You can test whether link is valid or not using:
[[ -f "$link" ]] && echo "points to a valid file"
To check if it is indeed a link use -L:
[[ -L "$link" ]] && echo "it's a link"
There seems to be a program named symlinks that does, among other things, what you're looking for.

restore in linux bash scripting

Help needed. This is script that I use to perform a restoration of a file from dustbin directory to its original location. It was located before in root. Then using other script it was "deleted" and stored in dustbin directory, and its former location was documented in storage file using this:
case $ans in
y) echo "`readlink -f $1`" >>home/storage & mv $1 /home/dustbin ;;
n) echo "File not deleted." ;;
*) echo "Please input answer." ;;
esac
So when using the script below I should restore the deleted file, but the following error comes up.
#!/bin/sh
if [ "$1" == "-n" ] ; then
cd ~/home/dustbin
restore="$(grep "$2" "$home/storage")"
filename="$(basename "$restore")"
echo "Where to save?"
read location
location1="$(readlink -f "$location")"
mv -i $filename "$location1"/$filename
else
cd ~/home
storage=$home/storage
restore="$(grep "$1" "$storage")"
filename="$(basename "$restore")"
mv -i $filename $restore
fi
error given - mv: missing file operand
EDIT:
so okay, I changed my script to something like this.
#!/bin/sh
if [ $1 ] ; then
cd ~/home
storage=~/home/storage
restore="$(grep "$1" "$storage")"
filename="$(basename "$restore")"
mv -i "$filename" "$restore"
fi
and still I get error:
mv: cannot stat `filename': No such file or directory
You might want to do some basic error handling to see if $filename exists before you use it as part of mv:
For example, before:
mv -i $filename "$location1"/$filename
You should probably do a:
if [[ -e "$filename" ]]; then
# do some error handling if you haven't found a filename
fi
The -e option checks whether the next argument to [[ refers to a filename that exists. It evaluates to true if so, false otherwise. (Alternatively, use -f to check if it's a regular file)
Or at least:
if [[ -z "$filename" ]]; then
# do some error handling if you haven't found a filename
fi
The -z option checks whether the next argument to [[ is the empty string. It evaluates to true if so, false otherwise.
Similar comment about: mv -i $filename $restore in your else clause.
Here's a list of test options.
You do
cd ~/home
and
mv -i "$filename" "$restore"
while the file is located in the dustbin directory, therefore, it is not found.
Do either
cd ~/home/dustbin
or
mv -i "dustbin/$filename" "$restore"
or just do
mv -i "~/home/dustbin/$filename" "$restore"
and drop the cd.

Resources