I am use a if command if filename then move file
this is what I have so far
filename=$*test*
if [ -f "filename" ]
then
mv filename archive/filename
else
echo "no filename exists"
fi
When I run the script I get "no filename exists"
How can I use a wildcard as a variable?
Your script has several problems.
filename=$*test*
$*test* is not valid bash syntax. The $ indicates a variable.
I am looking for test to be a wild card for a part of a filename
If that is the case, you need to drop the leading $. Or possibly what you meant was *${test}*.
mv filename archive/filename
This would move a file named "filename", which is likely not what you want. You probably want:
mv "$filename" archive/
If you are not renaming the file, you do not need to specify the name in the target.
If you change this line:
echo "no filename exists"
to:
echo "no $filename exists"
Include the dollar sign and you will see exactly what file the script tried to look for.
Some additional notes:
Include set -x at the start of your script. This will show you each command expanded so you can see what is actually happening.
Have a look at https://www.shellcheck.net/ which can pick up a lot of syntax errors.
Related
I'm trying to make a script that would test whether my file is exactly as it should be, but I haven't been using bash before:
#!/bin/bash
./myfile <test.in 1>>test.out 2>>testerror.out
if cmp -s "test.out" "pattern.out"
then
echo "Test matches pattern"
else
echo "Test does not match pattern"
fi
if cmp -s "testerror.out" "pattern.err"
then
echo "Errors matches pattern"
else
echo "Errors does not match pattern"
fi
Can I write it in such way that after calling ./script.sh myfile pattern my scripts would run over all files named pattern*.in and check if myfile gives same files as pattern*.out and pattern*.err ? e.g there are files pattern1, pattern2, pattern4 and i want to run test for them, but not for pattern3 that doesn't exist.
Can I somehow go around creating new files? (Assuming i don't need them) If I were doing it from command line, I'd go with something like
< pattern.in ./myfile | diff -s ./pattern.out
but I have no idea how to write it in script file to make it work.
Or maybe i should just use rm everytime?
If I understand you correctly:
for infile in pattern*.in ; do
outfile="${infile%.in}.out"
errfile="${infile%.in}.err"
echo "Working on input $infile with output $outfile and error $errfile"
./myfile <"$infile" >>"$outfile" 2>>"$errfile"
# Your `if`..`fi` blocks here, referencing infile/outfile/errfile
done
The % replacement operator strips a substring off the end of a variable's value. So if $infile is pattern.in, ${infile%.in} is that without the trailing .in, i.e., pattern. The outfile and errfile assignments use this to copy the first part (e.g., pattern1) of the particular .in file being processed.
I am running a shell script on my mac, and i am getting a "No Such file or directory.
The input is: the replacement_name, and the working dir.
The output is: changing all files in the directory from $file to $newfilename
#!/bin/sh
echo "-------------------------------------------------"
echo "Arguments:"
echo "Old File String: $1"
echo "New File Name Head: $2"
echo "Directory to Change: $3"
echo "-------------------------------------------------"
oldname="$1"
newname="$2"
abspath="$3"
echo "Updating all files in '$abspath' to $newname.{extension}"
for file in $(ls $abspath);
do
echo $file
echo $file | sed -e "s/$oldname/$newname/g"
newfilename=$("echo $file| sed -e \"s/$oldname/$newname/g\"")
echo "NEW FILE: $newfilename"
mv $abspath/$file $abspath/$newfilename
done
It seems that it doesnt like assigning the result of my 1-liner to a variable.
old_filename_string_template.dart
test_template.dart
./bulk_rename.sh: line 16: echo old_filename_string.dart| sed -e "s/old_filename_string/test/g": No such file or directory
NEW FILE:
Test Information:
mkdir /_temp_folder
touch old_filename_string_template.a old_filename_string_template.b old_filename_string_template.c old_filename_string1_template.a old_filename_string1_template.b old_filename_string1_template.c old_filename_string3_template.a old_filename_string3_template.b old_filename_string3_template.c
./convert.sh old_filename_string helloworld /_temp_folder
The double quotes here make the shell look for a command whose name (filename, alias, or function name) is the entire string between the quotes. Obviously, no such command exists.
> newfilename=$("echo $file| sed -e \"s/old_filename_string/$1/g\"")
Removing the double quotes inside the parentheses and the backslashes before the remaining ones will fix this particular error.
The construct $(command sequence) is called a command substitution; the shell effectively replaces this string with the standard output obtained by evaluating command sequence in a subshell.
Most of the rest of your script has much too few quotes; so it's really unclear why you added them here in particular. http://shellcheck.net/ is a useful service which will point out a few dozen more trivial errors. Briefly, anything which contains a file name should be between double quotes.
Try to put double quotes outside backticks/subtitutions (not INSIDE backticks/substitutions like $("..."))
newfilename="$(....)"
By the way, please consider to use the package perl rename which already does this bulk file rename very well, with Perl regex style which is easier to use. This perl rename command maybe alreay available in your (Mac) distro. See intro pages.
I have a list of file in variable list_of_files. So if I run the following commands
for file_path in $list_of_files; do
echo "=${file_path}="
done
It gives me this
=./a.py=
=./b.py=
=./c.py=
which means file_path contains a relative path to file, without any redundant spaces before or after.
But if I use cat instead of echo, it complains "No such file or directory"
for file_path in $list_of_files; do
cat ${file_path}
done
But what's interesting is, if I call cat directly cat ./a.py, it works.
It is not a cat-specific problem. It turns out if I check the file existence using if statement, it tells me those files do not exist.
for file_path in $list_of_files; do
if [ -f "$file_path" ]
then
echo 'OK'
else
echo 'NO'
fi
done
Result:
NO
NO
NO
Tried following approaches, but also failed.
Use full absolute path
Remove ./ from all file paths
The reason turns out to be that $list_of_files is colored. So it contains some special characters for coloring purpose but hidden!
I found that using echo "$list_of_files" | od -An -tcx1 (thanks to #BinaryZebra), which displays all the junks coloring the file names.
By using sed -r "s:\x1B\[[0-9;]*[mK]::g", I ruled out those magic bits!
I'm working on a shell script that will copy all the files from the command line to a directory. If the command line arguments contain any duplicate files, I want to prompt the user to either overwrite the existing file (it should now be in the directory), don't copy it, or rename it and then copy it.
What is the best way to approach this problem?
Here's some pseudocode of what I'm thinking:
for var in "$#"
do
for file in "$dirName" #unsure about this syntax too
do
if [ file or directory with name "$fileName" exists]; then
prompt user with options #i can handle this part :)
else
mv $var $dirName
fi
done
done
You are overcomplicating things.
for var in "$#"
do
if [ -e "$dirname/$var" ]; then
prompt user with options #i can handle this part :)
else
mv "$var" "$dirName"
fi
done
Make sure you use adequate quoting everywhere, by the way. Variables which contain file names should basically always be double quoted.
I am new to shell scripting, I have this script:
#!/bin/bash
path_file_conf=/fullpath/directory/*.conf
if [ -e "$path_file_conf" ];then
echo "Found file"
else
echo "No found file"
fi
The result is always "No found file" even if I have a .conf files inside /fullpath/directory/ folder.
May I know what part of the code is wrong?
Thanks in advance!
I would try something like this:
for filename in /fullpath/directory/*.conf
do
if [ -e "$filename" ] # If finds match...
then
echo "Found file"
echo
else
echo "No found file"
fi
done
I haven't tested so I'm not certain it works, but it will at least give you the overall strategy.
The expression:
path_file_conf=/fullpath/directory/*.conf
May have multiple path names that match. So the value of $path_file_conf may end up being, for example:
/fullpath/directory/foo1.conf /fullpath/directory/foo2.conf
The conditional:
if [ -e "$path_file_conf" ]; then
Checks for the existence of a single file. If "/fullpath/directory/foo1.conf /fullpath/directory/foo2.conf" doesn't name a "single file", which it won't, then the condition will fail even though the files exist.
You could check this way. If the path doesn't expand, it will fail and exit. If it finds at least one good path, it will succeed and exit.
for pf in $path_file_conf ; do
if [ -e "$pf" ] ; then
echo "Found"
break
else
echo "Not found"
fi
done
The line causing trouble is:
path_file_conf=/full/path/directory/*.conf
The shell does not do wild-card expansion on the name when there are multiple files to match, or when no files match, so (except in the unusual circumstance of having a file called *.conf with an asterisk) the -e test fails. There is probably an option in bash to generate an error when a wild card fails to match; I would never use it.
You can use:
path_file_conf=( /full/path/directory/*.conf )
This gives you an array with the names of the files as the elements of the array. However, if there are no files that match, it gives you the name as written as the only element of the array.
From there, you can check each file in turn:
for conf_file in "${path_file_conf[#]}"
do
if [ -e "$conf_file" ]
then echo "Found file $conf_file"
else echo "No such file as $conf_file"
fi
done
You can determine the number of names with ${#path_file_conf[#]}, but remember that 1 could indicate a real file or a non-existent file.