how can i select file with several directories below? [duplicate] - linux

I would like to write the following function in bash:
go() {
cd "~/project/entry ${1}*"
}
What this would do is to cd into a project subdirectory with prefix entry (note space) and possibly a long suffix. I would only need to give it a partial name and it will complete the suffix of the directory name.
So, if for example, I have the following folders:
~/project/entry alpha some longer folder name
~/project/entry beta another folder name
~/project/entry gamma
I can run go b and it will put me into ~/project/entry beta another folder name.
The problem is, of course, that the wildcard doesn't expand inside double quotes. I cannot omit the quotes because then I will not be able to capture the spaces properly.
How do I get the wildcard to expand while at the same time preserving the spaces?

Move the quotes. Just don't quote the *. Probably also good not to quote the ~.
go() {
cd ~/"project/entry ${1}"*
}
That being said if this matches more than one thing cd will use the first match and ignore all the other matches.

Related

Bash script - split String in two variables

In a Bash script I want to split a string into two other strings based on the last "/" it contains.
In a situation where the given string is "Example/Folder/Structure", I would like to create two other strings with the following values:
string 1 = "Example/Folder"
string 2 = "Structure"
I'm trying to create a script to get a slather coverage report for a given folder in an iOS app. Although I have minimal knowledge of Bash, I was able to get it to work when the given folder is located in the root of the project. Now I want to make the script able to handle paths so that I can get the report also for subfolders, and for that I need to differentiate the desired folder from the rest of the path.
basename(1), dirname(1):
path=a/b/c
basename=$(basename "$path") # c
dirname=$(dirname "$path") # a/b
Prefix/suffix removal:
path=a/b/c
basename=${path##*/} # c
dirname=${path%/*} # a/b
Prefix/suffix removal is sufficient in some circumstances, and faster because it's native shell.
dirname/basename commands are slower (especially many paths in a loop etc) but handle more variable input or directory depth.
Eg. dirname "file" prints ., but suffix removal would print file. dirname /dir prints /, but suffix removal prints empty string; dirname also handles contiguous slashes (dirname a//b); basename a/b/ prints b, but prefix removal prints empty string.
If you know the structure is always 3 slashes (a/b/c), it may be safe to use prefix/suffix removal. But here I would use basename and dirname.
Also think about whether a better approach is to change the working directory with cd, so you can just refer to current directory with . (there's also $PWD and $OLDPWD).

How to create an alias with relative pwd + string

I want to set an alias to switch from two WordPress instances on the CLI. Each of them have the same paths except for the names of their respective sites e.g:
srv/deployment/work/sitename1/wp-content/uploads/2018/
srv/deployment/work/sitename2/wp-content/uploads/2018/
How do I create an alias that takes the "pwd" of the current location and cd
s to exactly the same location on the other site?
How about a bash function instead of an alias, gives you a little more freedom.
Save this bash function to a file like switchsite.sh. Modify the variables to your needs. Then load it into your bash with:
source switchsite.sh
If you are in /srv/deployment/work/sitename1/wp-content/uploads/2018, do
switchsite sitename2
and you will be in /srv/deployment/work/sitename2/wp-content/uploads/2018.
switchsite() {
# modify this to reflect where your sites are located, no trailing slash
where_my_sites_are=/srv/deployment/work
# modify this so it includes all characters that can be in a site name
pattern_matching_sitenames=[a-z0-9_\-]
# this is the first argument when the function is called
newsite=$1
# this replaces the site name in the current working directory
newdir=$(pwd | sed -n -e "s#\($where_my_sites_are\)/\($pattern_matching_sitenames\+\)/\(.*\)#\1/$newsite/\3#p")
cd $newdir
}
How it works: The sed expression splits the output of pwd into three parts: what is before the current site name, the current site name, and what comes after. Then sed puts it back together with the new site name. Just make sure the pattern can match all characters that could be in your site name. Research character classes for details.
Add the below lines into ~/.bash_aliases
export sitename1=srv/deployment/work/sitename1/wp-content/uploads/2018/
export sitename2=srv/deployment/work/sitename2/wp-content/uploads/2018/
After that
source ~/.bash_aliases
Then you can simply type sitename1 and sitename2 from anywhere to switch to respective directories

Bash script for loop variable returns all files in directory rather than a single file name [duplicate]

I would like to write the following function in bash:
go() {
cd "~/project/entry ${1}*"
}
What this would do is to cd into a project subdirectory with prefix entry (note space) and possibly a long suffix. I would only need to give it a partial name and it will complete the suffix of the directory name.
So, if for example, I have the following folders:
~/project/entry alpha some longer folder name
~/project/entry beta another folder name
~/project/entry gamma
I can run go b and it will put me into ~/project/entry beta another folder name.
The problem is, of course, that the wildcard doesn't expand inside double quotes. I cannot omit the quotes because then I will not be able to capture the spaces properly.
How do I get the wildcard to expand while at the same time preserving the spaces?
Move the quotes. Just don't quote the *. Probably also good not to quote the ~.
go() {
cd ~/"project/entry ${1}"*
}
That being said if this matches more than one thing cd will use the first match and ignore all the other matches.

bash handling of quotation marks in filename

I am trying to remove and replace quotation marks that are present in a file name. For example, I would like to change:
$ ls
abc"def"ghi"jkl"mno
to this
$ ls
abc:def:ghi:jkl:mno
In trying to solve this, I came across How to rename a bunch of files to eliminate quote marks, which is exactly what I want to do. However, it didn't work for my case. To figure out why, I tried creating a test file like this:
$ touch abba\"abba\"cde\"cde\"efef
With this file, the solutions I came across (such as mentioned above) worked. But why didn't it work for the first file?
One thing I discovered was that bash command completion sees them differently. If I type in
$ ls abb<tab>
bash will complete the filename like so:
$ abba\"abba\"cde\"cde\"efef
just as I created it. But for the original file, bash completion went like this:
$ ls abc<tab>
results in
$ abc"def"ghi"jkl"mno
So in the test case file, there is an escape of the quotation marks, and in the other case (the file I really want to rename), there is no escaping of the the quotation marks. I don't know how the original files were named.
Can anyone explain why bash sees these names differently, and how I would go about renaming my file?
Here is two ways to rename a file with "(quotation) mark,
option 1: With escape character \
mv abc\"cdf\"efg\"hij newFileName
option 2: By using '(single quote)
mv 'abc"cdf"efg"hij' newFileName
Note: using special charaters like :(colon) in file name might not be a good idea,
and regarding the auto completion, it usually fill the name with escape character, example
ls abc<tab> will complete the name to ls abc\"cdf\"efg\"hij
unless you start the name with a quote, example
ls 'abc<tab> will complete the name to ls 'abc"cdf"efg"hij'

glob for all folders within a folder except one named folder

I am writing my Karma conf based on
http://karma-runner.github.io/1.0/config/preprocessors.html
The key for the preprocessor is a glob string.
This works for all folders within the build folder:
build/**/!(*.spec|*.bundle|*.min).js
However, I don't want all folders. I wanted folder 1,2,4,5 NOT folder 3
Can I write that in a single string (as seems to be required by karma)?
Something like
build/(folder1|folder2|folder4|folder5)/!(*.spec|*.bundle|*.min).js
or even better
build/** but not folder 3/!(*.spec|*.bundle|*.min).js
This covers it
https://github.com/karma-runner/karma-coverage/issues/13
Quoting it
You can make this work using brace expansion. For #chevalric's case, the following pattern will do it:
src/*/{*.js,!(test)/**/*.js}
This expands to two patterns:
src/*/*.js # Match files in the module root
src/*/!(test)/**/*.js # Match files in all subfolders except test/
Also it later says ..
src/*/!(test)/**/*.js
worked
However, for me, I could not test that this worked for various reasons.

Resources