I have the file $HOME/foo/foo.mov
if [[ -f $HOME/**/*.mov ]]; then
echo "file is there" else
echo "file is not there"
fi
echoes "file is not there". whereas,
if [ -f $HOME/**/*.mov ]]; then
echo "file is there" else
echo "file is not there"
fi
echoes "file there".
Why is the difference between [[ ]] and [ ]?
Arguments to the [ command are subject to pathname expansion; the words used inside [[ ... ]] are not.
If you are getting file is there, I suspect you have exactly one file that matches the pattern. Otherwise, you would have too many arguments for -f, or the pattern would be treated as a literal string that does not name an existing file.
Related
I have an array of possible file extensions, which contains some wild cards e.g.:
FILETYPES=("DBG" "MSG" "OUT" "output*.txt")
I also have a list of files, which I am grabbing the file extension from. I then need to compare the extension with the array of file extensions.
I have tried:
if [[ ${EXTENSION} =~ "${FILETYPES[*]}" ]]; then
echo "file found"
fi
if [[ ${EXTENSION} == "${FILETYPES[*]}" ]]; then
echo "file found"
fi
and
if [[ ${EXTENSION} =~ "${FILETYPES[*]}" ]]; then
echo "file found"
fi
But to no avail
I tried:
if [[ "${FILETYPES[*]}" =~ ${EXTENSION} ]]; then
echo "file found"
fi
However, it ended up comparing "txt" to "output*.txt" and concluding it was a match.
FILETYPES=("DBG" "MSG" "OUT" "output*.txt") First of all, avoid ALL_CAPS variable names except if these are meant as global environment variables.
"output*.txt": is ok as a globing pattern, for bash test [[ $variable == output*.txt ]] for example. But for Regex matching it needs a different syntax like [[ $variable =~ output.*\.txt ]]
"${FILETYPES[*]}": Expanding this array into a single_string was mostly a good approach, but it needs clever use of the IFS environment variable to help it expands into a Regex. Something like IFS='|' regex_fragment="(${array[*]})", so that each array entry will be expanded, separated by a pipe | and enclosed in parenthesis as (entry1|entry2|...).
Here is an implementation you could use:
textscript.sh
#!/usr/bin/env bash
extensions_regexes=("DBG" "MSG" "OUT" "output.*\.txt")
# Expands the extensions regexes into a proper regex string
IFS='|' regex=".*\.(${extensions_regexes[*]})"
# Prints the regex for debug purposes
printf %s\\n "$regex"
# Iterate all filenames passed as argument to the script
for filename; do
# Compare the filename with the regex
if [[ $filename =~ $regex ]]; then
printf 'file found: %s \n' "$filename"
fi
done
Sample usage:
$ touch foobar.MSG foobar.output.txt
$ bash testscript.sh *
.*\.(DBG|MSG|OUT|output.*\.txt)
file found: foobar.MSG
file found: foobar.output.txt
You cannot directly compare a string with an array. Would you please try something like:
filetypes=("DBG" "MSG" "OUT" "output*.txt")
extension="MSG" # example
match=0
for type in "${filetypes[#]}"; do
if [[ $extension = $type ]]; then
match=1
break
fi
done
echo "$match"
You can save looping with regex:
pat="^(DBG|MSG|OUT|output.*\.txt)$"
extension="output_foo.txt" # example
match=0
if [[ $extension =~ $pat ]]; then
match=1
fi
echo "$match"
Please note the expressions of regex differ from wildcards for globbing.
As a side note, we conventionally do not use uppercases for user variables to avoid conflicts with system variables.
i have a file called MYNAME in path /root/user/
which has some value say SSS_14_10_1992
when the values exists in file the below code works fine
but when the file is empty , then the below mentioned error is thrown
i am reading this value from file and matching it wildcard and doing something , when the file has some value the below code works fine , when the file is empty then i am getting conditional error
Below is my code
var=$(cat /root/user/MYNAME)
echo $var
su - uname<<!
pwd
if [ -z "$var" ]; then
echo "NAME SHOULD BE PROVIDED IN MYNAME FILE"
else
if [[ $var == SSS_14_10* ]]
then
echo "value is matched"
else
echo "value has not matched"
fi
fi
!
when the file is empty
i am getting the below error:
: conditional binary operator expected
: syntax error near `SSS_14_10*'
: ` if [[ == SSS_14_10* ]]'
Try to compare "$var" (with quotes) instead of $var (without quotes). This way if the variable is empty you're just comparing "".
Don't generate code dynamically like this. Pass the value of $var as a parameter to the script run by su.
var=$(cat /root/user/MYNAME)
echo "$var"
su - uname<<'!' "$var"
pwd
if [ -z "$1" ]; then
echo "NAME SHOULD BE PROVIDED IN MYNAME FILE"
elif [[ $1 == SSS_14_10* ]]; then
echo "value is matched"
else
echo "value has not matched"
fi
!
Note the single quotes around the here-doc delimiter; this ensures the here document is seen as-is by su, so that nothing further needs escaping.
This time Bash question.
I am doing a script that will require user input "read -p".
The problem is that file name is in that format: vNN_NN_nn_nn_nn.zip. For example v3_11_1_2.zip or v_1_1_1_1_22.zip
I can add into script "v" to be up front - no problem.
The problem is how to read only [0-9] and [_] as a input parameter.
I tried all combinations and no success.
read -p "Please enter file name like 1_2_03_04: " filename
if [ ! $filename =~ ^[0-9]+$ ] || [! $zip =~ ^[_]+$ ]; then
echo "Filename is not valid"
else
echo "filename is $filename"
fi
No success so far. How that can be done?
Thank you.
There are a couple of changes I would make. First, be sure to use [[...]] rather than [...], as the former is BASH, and the later is just sh. The regex syntax is not just sh.
Next, you'll want to include both checks in the same regex. The [...] groups in regex can contain all the characters that you want to include.
Try this solution:
read -p "Please enter file name like 1_2_03_04: " filename
if [[ ! $filename =~ ^[0-9_]+$ ]] ; then
echo "Filename is not valid"
else
echo "filename is $filename"
fi
To support your format of filenames, I suggest using this regex:
re='^v[0-9]*(_[0-9]+)+$'
read -p "Please enter file name like v1_2_03_04: " file
[[ $file =~ $re ]] && echo "$file is valid" || echo "$file is not valid"
This will not allow weird looking filenames such as v____ or v12____ or v12_1_
RegEx Demo
#!/bin/bash
file=/home/yaal/temp/hatch/*;
if [[ -f $file ]]; then
echo $file
else
echo "No files found"
fi
I have files under hatch dir but it is displaying "No files found". why is it?
Thanks !!
Pathname expansion does not occur on the right-hand side of a non-array variable assignment, so file contains a literal *, not a list of file names. Pathname expansion is not performed inside [[ ... ]] either, so you are asking if there is a file named * exists in /home/yaal/temp/hatch`.
If you just want to know if there is at least one file (excluding files starting with .) in hatch, try
for f in /home/yaal/temp/hatch/*; do
if [[ -f $f ]]; then
echo "$file"
else
echo "No files found"
fi
break
done
You can also fill an array, then check if it is empty or not:
files=( /home/yaal/temp/hatch/* )
if (( ${#files[#]} > 0 )); then
echo "${files[0]}" # First file found
else
echo "No files found"
fi
If you do want to consider file names beginning with ., either use shopt -s dotglob, or use two patterns /home/yaal/temp/hatch/* /home/yaal/temp/hatch/.*.
Ideally you'd want to use for loop to check if file exists because the pathname expansion does not happen inside [[ ... ]]. Use something like:
#!/bin/bash
for file in /home/yaal/temp/hatch/*; do
if [[ -f $file ]]; then
echo $file
else
echo "No files found"
fi
done
I'm trying to check if a file exists using bash. This is my code
if [-e file.txt]; then
echo "file exists"
else
echo "file doesn't exist"
fi
But when I run it I get:
./test.sh: line 3: [-e: command not found
What am I doing wrong?
[ is not a special token in Bash; it's just that the word [ is a builtin command (just like echo). So you need a space after it. And, similarly, you need a space before ]:
if [ -e file.txt ] ; then
That said, I recommend [[ ]] instead — it's safer in a few ways (though it still requires the spaces):
if [[ -e file.txt ]] ; then
if [ -e file.txt ]; then
You need spaces.
[ and ] are regular programs.
Woops, turns out I needed a space between [ and -e. Like this:
if [ -e file.txt ]; then
echo "file exists"
else
echo "file doesn't exist"
fi
the '[' and ']' needs to be 'on--their-own', i.e. surrounded by spaces.
if [ -e file.txt ] *emphasized text*; then
echo "file exists"
else
echo "file doesn't exist"
fi