Bash shell script postprocessing results of ls [duplicate] - string

This question already has answers here:
What is the meaning of the ${0##...} syntax with variable, braces and hash character in bash?
(4 answers)
What does "##" in a shell script mean? [duplicate]
(1 answer)
Closed 7 months ago.
I came across a shell script like the following:
for FILE_PATH in `ls some/directory`
do
export FILE=${FILE_PATH##*/}
done
What exactly is the "##*/" doing? When I echo ${FILE} and ${FILE_PATH}, I don't see any difference. Is this to handle unusually named files?
More generally, how would I go about figuring out this type of question for myself in the future? Google was completely useless.

It's removing everything up to the last / in the value of $FILE. From the Bash Manual:
${parameter#word}
${parameter##word}
The word is expanded to produce a pattern and matched according to the rules described below (see Pattern Matching). If the pattern matches the beginning of the expanded value of parameter, then the result of the expansion is the value of parameter with the shortest matching pattern (the ‘#’ case) or the longest matching pattern (the ‘##’ case) deleted.
You're not seeing any difference in this case because when you list a directory it just outputs the filenames, it doesn't include the directory portion, so there's nothing to remove. You would see the difference if you did:
for FILE in some/directory/*

Related

Removing everything after last hyphen in a string in Bash script? [duplicate]

This question already has answers here:
How can I remove all text after a character in bash?
(7 answers)
Closed last month.
Working on a script where I need to take a string, and remove everything after the last occurence of a certain character. In this case a hyphen.
For example, This-is-a-filename-0001.jpg should result in This-is-a-filename
You can cut strings in bash:
line="This-is-a-filename-0001.jpg"
echo "${line%-*}" # prints: This-is-a-filename
The %-*operator removes all beginning with the last hyphen.
You're looking for a sed within your script, something close to what's below.
sed 's!/[^/]*$!/!'
Generally, I would say, please do research before posting a question like yours since it's relatively easy to find the answers

Matching a pattern in cat/zcat? [duplicate]

This question already has answers here:
bash wildcard n digits
(4 answers)
Closed 2 years ago.
How can I match a more complex pattern when using cat or zcat? For example, I know I can do this:
zcat /var/log/nginx/access.log.*.gz
Which will output all the gzipped access logs to stdin.
What if I want a more complex pattern? Say, all the log files that are between 1-15, e.g. something like this pattern:
zcat /var/log/nginx/access.log.([1-9]|1[0-5]).gz
This results in an unexpected token which is obvious, but I'm not sure how I'd escape the regex in this situation? Maybe I need to pipe ls output to zcat instead?
It depends of course on specifically what pattern you want to match. For the example you have given of log files 1-15, you could use something like
cat /var/log/nginx/access.log.{1..15}.gz
which will complain to stderr if any of those numbers don't exist, but it will still concatenate the rest to stdout.
This technique is a "sequence expression" if you want to look it up - it's a part of brace expansion.

How to rename multiple files in a directory leaving the extension in Linux [duplicate]

This question already has answers here:
How to rename files without changing extension in Linux 102221.pdf to 102221_name.pdf
(3 answers)
Rename multiple files based on pattern in Unix
(24 answers)
Closed 4 years ago.
I need to rename files in a directory taking out a string of characters that is different with each file but starts the same way. I know how to strip characters from the filename, but how do I preserve the extension? I know it's a variation of a common question but I can't find a answer that fits my exact need.
Redshirts_ep6_dSBHpCsvQ3BfQ7-NNIjXYO4pnHpNMvu7bfvURLF3BSzB_3YOOrBBoNnICTR-hg.mp3
-> Redshirts.mp3
PathsNotTaken_ep6_XWixFER4PJyeozVfcxT96UajpnVI7cRMRhAU4Aj9-rpeacnBleuGY9zCPDe0aQ.mp3
-> PathsNotTaken.mp3
The linux command rename is super helpful here. It can use regex to perform the renaming.
This can probably rewritten a bit, but it appears do to the job here:
rename -n 's/(^[^_]*)_.*/$1.mp3/' *.mp3
Just remove that -n flag to run for for real. Leaving it on is just a test.
This regex says:
Characters at the start of the line ^ that don't contain an underscore [^_] repeated any number of times * are captured into a capture group (^[^_]*) if they are followed by an underscore and any number of any other characters _.*. These are then rewritten by using that first capture group $1 followed by .mp3

Can multiple BASH variable manipulations be used at once? [duplicate]

This question already has answers here:
Can parameter expansion be nested in Bash? [duplicate]
(2 answers)
Can ${var} parameter expansion expressions be nested in bash?
(15 answers)
Closed 4 years ago.
Is it possible to perform more than one bash variable manipulation in one shot?
For example:
# for this variable
foo="string_that_is_lower"
# can I do this in one shot?
$foo="${foo:0:4}"
echo "${foo^^}"
Is there a way to combine these? I realize this is a trivial problem because this works just fine, or one could simply use other built in tools like echo ${foo:0:4} | tr [[:lower:]] [[:upper:]], but that is lame.
I've tried every logical combination I can think might work:
${${foo^^}:0:4}
${{foo^^}:0:4}
${foo^^,:0:4}
${foo^^;:0:4}
${foo^^ :0:4}
All produce syntax errors.
I find no instances of "(combine|multiple) bash variable manipulations" in the Advanced Bash Scripting Manual, or the manpage, or Google, or here, so maybe you just can't do it, but probably I'm just not searching for the right terms.
It is a very good question, but not something that parameter expansion allows. man bash provides that expansion operates on a parameter name or symbol, e.g.
Parameter Expansion
The `$' character introduces parameter expansion, command
substitution, or arithmetic expansion. The parameter name or
symbol to be expanded may be enclosed in braces, which are optional
but serve to protect the variable to be expanded from characters
immediately following it which could be interpreted as partof the
name.
When you seek to chain expansions together, you are attempting to use the text that results from the first expansion as a parameter name or symbol (which it isn't), so the command fails with a syntax error.
Good question!
(note: to be complete -- there are some instances where you can embed a parameter expansion within another parameter expansion, but those are limited to where the outer expansion is looking for a single number as part of its expansion which can be provided by an included expansion such as the length of a string, e.g. ${#var} in v=foo; echo ${v:$((${#v}-1))})

How to Format grep Output When Saving to a Variable [duplicate]

This question already has answers here:
How to preserve line breaks when storing command output to a variable?
(2 answers)
Closed 7 years ago.
If I grep our syslogs for a specific term, I get a nice output of those logs matching my term and each entry on a separate line.
If I save that to a variable so I can use it in a script as such:
results=$( grep "term" logs )
echo $results
then all the logs run together and are not human readable.
How can I make it look cleaner so when I do echo $results, I can actually read the output?
Thanks,
Quote it:
echo "$results"
This preserves all the whitespace, instead of using it for word splitting.
In general, you should almost always quote variables, unless you have a specific reason not to.

Resources