I'm trying this, but I'm clearly doing something wrong beyond my comprehension :(
sv () { ls -la ~/releases | grep -i $1 | perl -l -ne "/($1.*$)/ && print $1"; }
I'm getting this:
$ sv blah
drwxr-xr-x 10 bob staff 320B Dec 30 07:12 blah-1.2.3
but I would like this:
$ sv blah
blah-1.2.3
CodePudding user response:
Using shell expansion on wildcard *
touch blah-1.2.3
mkdir ~/releases
sv() ( shopt -s nullglob; for file; do ls -d "$file"*; done )
sv bla ~/relea
Output
blah-1.2.3
/home/me/releases/
DO NOT USE ls' output for anything. ls is a tool for interactively looking at directory metadata. Any attempts at parsing ls output with code are broken. Globs are much more simple AND correct: for file in *.txt. Read http://mywiki.wooledge.org/ParsingLs
CodePudding user response:
The problems are do to code injection bugs, both into the Perl program, and into the regex literal.
See How can I process options using Perl in -n or -p mode? for ways to avoid generating Perl code from the shell.
id="$1" perl -nle'/(?:^|\/)\Q$ENV{id}/ && print $ENV{id}'
perl -snle'/^(?:^|\/)\Q$id/ && print $id' -- -id="$1"
But there are better approaches. See the other answer(s).
CodePudding user response:
If OP insists on parsing the ls output ...
$ sv () { 'ls' -la ~/releases | awk -v str="$1" 'tolower($(NF))~tolower(str) {print $(NF)}'; }
bah-1.2.3
NOTES:
'ls'to disable use of any aliasestolower()- wrapper for both sides of~to facilitate a case-insensitive match$(NF)~str- if last field ($(NF)) contains the stringstrthen ...print $(NF)- print the last field ($(NF))- will not work correctly for files that contain white space
CodePudding user response:
One idea using find, xargs and basename:
sv () { find ~/releases -iname "*$1*" -print0 | xargs -0 -r basename -a; }
Taking for a test drive:
$ sv blah
blah-1.2.3
NOTES:
find / -iname- for case insensitive matching- the
find / -print0andxargs / -0options are included to address names with special characters (eg, linefeeds) in the name basename -a- apply basename to multiple names (eg,findpasses multiple matches toxargs); alternatively:xargs -n1 -r basenameto supply a single match at a time tobasename- this will also search any subdirectories of
~/releases; this can be modified withfindoptions-maxdepthand-mindepthas needed - this will match on anything with
blahin the name ... files, directories, symlinks, etc; this can be modified withfindtests like-type
