This question already has answers here:
How do I deal with a filename that starts with the hyphen (-) character?
(5 answers)
Closed 12 months ago.
I was attempting to use the xxd command in bash, and used the -r argument, but forgot to add the in-file and out-file. I now have a useless file named -r and I cant remove it due to it being an argument for almost any command that I can think of that would be able to delete files.
Is there any other way for me to remove this file?
To remove a file whose name starts with a -, use:
rm -- -r
or
rm ./-r
-- is used to signify the end of command options.
Related
This question already has an answer here:
In bash, how do I expand a wildcard while it's inside double quotes?
(1 answer)
Closed 2 years ago.
I’m trying to execute a shell command that deletes the content of the folder. This was executed on macOS Catalina.
This command works:
rm -r /path/folder/*
But this won’t work:
rm -r “/path/folder/*”
I wonder what is the effect of those quotes. The path changes because it is executed from my program. I added quotes in the path to make up for spaces in the path if it exists. Then I tested it in actual command line to check and it behaves like that.
The quotes are to block-escape paths containing space characters.
In case of an asterisk as a wildcard you have to keep the asterisk out of the block
rm -r "/path/my great folder"/*
An alternative is to escape each space character with a backslash.
rm -r /path/my\ great\ folder/*
This question already has answers here:
Brace expansion with variable? [duplicate]
(6 answers)
Closed 3 years ago.
I have a variable:
rules=L002,L003
This rules variable denotes the files to copy from /usr/lib/vera++/scrpts/rules directory. The extension for the files is .tcl.
I am doing something like:
cp -r /usr/lib/vera++/scripts/rules/{${rules}}.tcl .
What goes wrong is that ${rules} is treated completely as a string. But bash should translate that into:
cp -r /usr/lib/vera++/scripts/rules/{L002,L003}.tcl .
The easiest way to take an argument and make a command from this argument is to use eval command. In your case whole script will look like:
#!/bin/bash
rules=L002,L003
eval "cp -r /usr/lib/vera++/scripts/rules/{${rules}}.tcl ."
This question already has answers here:
Can ${var} parameter expansion expressions be nested in bash?
(15 answers)
Closed 4 years ago.
I have the follwing which creates a directory from a list of files:
for file in $(ls *.txt); do
folder=${file//.txt/ };
folder=${folder//./'/'};
folder=${folder//[[:space:]]/};
mkdir -p $folder;
done
Can I link the 3 string manipulation commands that assign folder into one line?
I've tried several things with no success. Is it possible to use the | operator somehow?
Bash cannot do this, but Z Shell (zsh) (which is very similar) can nest the replacements:
for file in *.txt; do
folder=${${${file//.txt/ }//./'/'}//[[:space:]]/};
mkdir -p $folder;
done
(You don't need to do $(ls *.txt) (parsing ls in this way is dangerous: you lose all spaces) since you can just give it *.txt, which properly handles spaces in filenames. This works in any POSIX shell.)
This question already has answers here:
How to pass the value of a variable to the standard input of a command?
(9 answers)
Closed 1 year ago.
I have a shell script:
TOPDIR=`pwd`
FOLDER=$($TOPDIR | sed 's/\//\_/g')
if [[ condition ]];then
source ~/[$FOLDER]-build/build-env.sh
fi
the TOPDIR here is /home/uname/project, so the variable FOLDER is supposed to be _home_uname_project because sed is called to replace / with _.
But it goes wrong when executing, terminal tells that /home/uname/[]-build/build-env.sh: No such file or directory which, I guess, means that FOLDER is unexpected empty in the if-then statement. Can anybody help me with figuring this out?
If you look at the output of just
$TOPDIR | sed 's/\//\_/g'
you'll realize that it's empty; it's trying to execute a command equal to the contents of $TOPDIR and pipe the output of that into sed, but there is no output in the first place.
You could do
pwd | sed 's\//_/g'
instead (no need to escape _), which would work.
Or, instead of using an external tool, you could use parameter expansion
topdir="$(pwd)"
topdir="${topdir//\//_}"
with the same result.
Notice that uppercase variable names are discouraged, as they're more likely to clash with existing, reserved names.
This question already has answers here:
How to skip the for loop when there are no matching files?
(2 answers)
Closed 3 years ago.
I want to loop over all files matching extension jpg or txt. I use:
for file in myDir/*.{jpg,txt}
do
echo "$file"
done
Problem: If the directory contains no jpg file at all, the loop will have one iteration with output myDir/*.jpg. I thought * will be replaced by an arbitrary file (and if no file exists it cannot be expanded). How can I avoid the unwanted iteration?
Use this to avoid the unwanted iteration:
shopt -s nullglob
From man bash:
nullglob: If set, bash allows patterns which match no files (see Pathname Expansion above) to expand to a null string, rather than themselves.
See: help shopt and shopt
This and a duplicate question both were in context of not just pathname-expansion, but also brace-expansion, and a duplicate asked for POSIX.
The compgen -G does bash --posix compatible pathname-expansion (no brace-expansion) and... you guessed it: yields nothing if there are no matches.
Therefore write a bash --posix function to do it. Brief outline: temporarily use set -f to first do brace-expansion (without pathname-expansion) via an echo, then apply compgen -G to each result for pathname-expansion. Full function left as an exercise.