I a, trying to create a file that begins with the symbol "-" but Unix wont let me do it. I also need to delete one but figured that if i can get one to create then I could use the same method to delete them. I have tried using double quotes and single quotes
How would you create and then delete a file that begins with the symbol -?
(Assuming command line here).
Indeed the shell will assume that strings on the command line starting with - are parameters, which are bound to not be valid.
Luckily you can explicitly tell the shell that all parameters are given and that the rest of the line are arguments, with --:
touch -- -hello
rm -- -hello
Related
realpath <<<'foo' fails "realpath: missing operand". I don't know what that means.
realpath <(<<<'foo') returns /proc/3443695/fd/pipe:[26244650] which I guess means it's creating a temporary pipe which will contain the string "foo".
Or maybe printf is more clear:
❯ printf "%q" <<<'foo' # no output
❯ printf "%q" <(<<<'foo')
/proc/self/fd/11%
The actual program I'm trying to call doesn't like either of those. I think I need an actual file.
I can do that in multiple commands by creating a file with mktemp and then writing to it, and then sending that off as the arg, but does zsh have any convenient syntax for doing this in-place? A 1-liner?
It looks like the =(list) process substitution should do what you want.
From the zshexpn man page:
If =(...) is used instead of <(...), then the file passed as an
argument will be the name of a temporary file containing the output
of the list process. This may be used instead of the < form for a
program that expects to lseek on the input file.
...
The temporary file created by the process substitution will be deleted when the function exits.
On my system, realpath =(<<<'foo') returns something like /private/tmp/zsh3YAdDx, i.e. the name of a temporary file that does indeed appear to be deleted after executing the command.
As a bonus, the documentation notes that in some cases the =(<<<...) form is optimized to execute completely in the current shell.
I want to write a bash script that takes a user input (which will be a filename) and replaces a path to a file inside a css file with that filename. For simplicity, the two files will be in the same folder and in the css code only the filename at the end of the path should be changed.
I thought of using regex to match any line of code that has a specific pattern and then change the end of it. I know about sed, but since the filename always changes I'm not sure how to solve this problem other than regex. I also thought of adding a variable in the css file that holds the filename as a value and then adding that variable at the end of the path, but I'm not sure then how to access that variable from a bash script.
Any recommendations on how to tackle this problem?
Thanks!
Edit Adding more Information:
Here is the line in the css file I want to edit. The part to be changed is the fileName.png at the end. Since it will change I thought of using a regex to "find" the correct spot in the css file.
background: #2c001e url(file:////usr/share/backgrounds/fileName.png/);
A regex matching only this line in this specific file is the following. It could probably be simplified, but I don't see a reason why since it should work too:)
(background)\:\s\#.{6}\s(url)\((file)\:\/{4}(usr)\/(share)\/backgrounds\/.+\.(png)\/\)\;
So, there are some ways to do that. You can check topic in links below. sed command is also good idea. But before executing it, you can build a new variable (or multiple variables) to use them in regex sed -e syntax.
Getting the last argument passed to a shell script
Maybe, if you will add some input and output examples, I could be more specific in this case.
To replace the input in the file at run-time you could use this line in a script
sed "s/stringToReplace/$1/g" templateFile >fileToUse
the $1 is referencing the 2nd bash script argument (the first being $0, the name of the invoking script). stringToReplace would be written in verbatim in the templateFile.
You could also use a script with two runtime arguments ($1, $2), and you would change the original contents of the fileToUse using the -i option. But this requires storage of the last file path to be used as argument $1.
I'm having problem with setting up simple function in ZSH.
I want to make function which downloads only mp3 file from youtube.
I used youtube-dl and i want to make simple function to make that easy for me
ytmp3(){
youtube-dl -x --audio-format mp3 "$#"}
So when i try
ytmp3 https://www.youtube.com/watch?v=_DiEbmg3lU8
i get
zsh: no matches found: https://www.youtube.com/watch?v=_DiEbmg3lU8
but if i try
ytmp3 "https://www.youtube.com/watch?v=_DiEbmg3lU8"
it works.
I figured out that program runs (but wont download anything) if i remove all charachers after ? including it. So i guess that this is some sort of special character for zsh.
By default, the ZSH will try to "glob" patterns that you use on command lines (it will try to match the pattern to file names). If it can't make a match, you get the error you're getting ("no matches found").
You can disable this behaviour by disabling the nomatch option:
unsetopt nomatch
The manual page describes this option as follows (it describes what happens when the option is enabled):
If a pattern for filename generation has no matches, print an error, instead of leaving it unchanged in the argument list.
Try again with the option disabled:
$ unsetopt nomatch
$ ytmp3 https://www.youtube.com/watch?v=_DiEbmg3lU8
If you want to permanently disable the option, you can add the disable command to your ~/.zshrc file.
The question mark is part of ZSH's pattern matching, similarly to *. It means "Any character".
For instance, ls c?nfig will list both "config" and "cinfig", provided they exist.
So, yes, your problem is simply that zsh is trying to interpret the ? in the URL as a pattern to match to files, failing to find any, and crapping out. Escape the ? with a \ or put quotes around it, like you did, to fix it.
I am taking a intro to Unix class and am stuck on the final assignment. I need to write a script to change the file extension of a filename that is input when the script is run. The new file extension is also input when the script is run. The script is call chExt1.sh . Our first trial of the script is run as follows
./chExt1.sh cpp aardvark.CPP
The script is suppose to change the second input file extension to the file extension given in the first input. It is not suppose to matter what file extension is given with the file name or what file extension is given as the new extension, nor is it only for changing uppercase to lowercase. In hope to make this very clear if given the following:
./chExt1.sh istink helpme.plEaSe
The script would change helpme.plEaSe to helpme.istink . I have searched on this forum and in google and have had no look with trying the different examples I found. Below is some of the examples I have tried and what I currently have.
Current
#!/bin/sh
fileExtension="$1"
shift
oldName="$2"
shift
newName=${oldName%%.*}${fileExtension}
echo $newName
The echo is just to see if it works, and if I get it working I'm going to add an mv to save it.
Others that I have tried:
newName=`${oldName%.*}`
newName=`${oldName#.*}`
sed 's/\.*//' $oldName > $newName
I can't seem to find some of the other sed I have used but they involved alot of backslashes and () with .* in there. I did not try the basename command cause I don't know the file extension to be entered and all I the examples I saw required that you specify what you wanted removed and I can't. I did not list all the different quote variations that I used but I have tried alot. My instructions say to use the sed command since we should know how to use that from class but when I try to do it I don't isolate just the ending of the file and I believe (cause it takes so long to finish) that it is going through the whole file and looking for .'s and anything after cause I kept doing .* as the pattern. Thanks for anyhelp you can give.
shift shifts the positional parameters, so after calling shift the second parameter ($2) is now the first ($1). The second shift is not necessary, because you are done accessing the parameters. You need to either remove the shift
#!/bin/sh
fileExtension="$1"
oldName="$2"
newName=${oldName%%.*}${fileExtension}
echo $newName
or change $2 to $1.
#!/bin/sh
fileExtension="$1"
shift
oldName="$1"
newName=${oldName%%.*}${fileExtension}
echo $newName
However, you are still missing a dot from your new file name. That is left as an exercise for the reader.
I am using the maven plugin appassembler to generate a unix script. In its tag, I put sth like:
<commandLineArguments>
<commandLineArgument>$1</commandLineArgument>
<commandLineArgument>$2</commandLineArgument>
<commandLineArgument>$3</commandLineArgument>
</commandLineArguments>
The resultant script, however, shows
$1 $2 $3 "$#"
I don't know where the last one came from, it therefore repeat the first 3 arguments.
Mojo's AppAssembler Maven Plugin generates a script that always appends all the command line arguments provided to the script onto the JVM's launch command. Thus if you did nothing, the "$#" will be the last thing on the JVM command used to start the program.
The <commandLineArguments> tag is used to inject additional command line arguments before the ARGLIST matcher.
It seems (to me) that you think you needed to add the positional markers in order to get the parameters passed through, hence the snippet you were adding. That is both:
Unnecessary, as by default the plugin generates a script that passes all required parameters.
Actually a potential bug, as what you have configured does not handle argument quoting and escaping correctly.
With regard to the second point consider the case where the second parameter is the name of a file that contains a space charater. If I launch the script for you program like so
$ bin/foo.sh Document.txt Document\ 2.txt "Copy of Document 3.txt" Doc4.txt
you will actually see the following being passed through to your Java program with the configuration you provided:
Document.txt (all of $1)
Document ($2 is expanded, but not quoted so now gets re-evaluated)
2.txt
Copy ($3 is expanded, but not quoted, so also gets re-evaluated, spaces seen as argument separator again)
of
Document
3.txt
Document.txt (now the ARGLIST matcher provides everything correctly)
Document 2.txt
Copy of Document 3.txt
Doc4.txt
The solution is simple. Stop trying to configure something you don't need to configure!