Matching directories in a directory - linux

Directory workspace contains like 5 projects:
project-1
project-2
project-3
project-4
project-5
I want to match all folders in this directory, but the array does not get populated when I use a variable:
workspace="~/workspace";
myDirectories=(${workspace}/project-*/);
If I pass it in manually it picks up the directories without a problem.
myDirectories=(~/workspace/project-*/);
I know it is something simple I am missing, but it is bugging me!

You have used quotes in workspace variable declaration like:
workspace="~/workspace"
So the ~ won't be expanded as the home directory, but would be treated literally.
You can:
Leave ~ outside quotes (note that, quotes are not strictly necessary in this case):
workspace=~/"workspace"
Or use $HOME instead of ~:
workspace="$HOME"/workspace
Or use absolute paths starting with / e.g. /home/username/workspace

The ~ won't work correctly (expand to user home directory) unless it is unquoted.
As an * also needs to be unquoted to expand.
You could define the directory as a fixed string (remove the leading ~):
workspace="workingdirectory" # or just workspace=workingdirectory
And leave all the expansions to the array definition (both work):
myDirectories=( ~/"${workspace}/"project-*/ );
myDirectories=( "${HOME}/${workspace}/"project-*/ );
You may use fixed directories like: "/home/user/$workspace/"project-*/ but in this case you lose the adaptability to any current user running the script without any real gain.
It is also possible to use the ~/ at the time of defining the variable workspace but that would also fix the user to the user running that part of the script, which may not be the same as the one doing the directory expansions.
All considered, expanding at the time of creating the array seems to b ethe best solution, and both solutions above work well.

Related

How to rename a folder that contains smart quotes

I have a folder that was created automatically. The user unintentionally provided smart (curly) quotes as part of the name, and the process that sanitizes the inputs did not catch these. As a result, the folder name contains the smart quotes. For example:
this-is-my-folder’s-name-“Bob”
I'm now trying to rename/remove said folder on the command line, and none of the standard tricks for dealing with files/folders with special characters (enclosing in quotes, escaping the characters, trying to rename it by inode, etc.) are working. All result in:
mv: cannot move this-is-my-folder’s-name-“Bob” to this-is-my-folders-name-BOB: No such file or directory
Can anyone provide some advice as to how I can achieve this?
To get the name in a format you can copy-and-paste into your shell:
printf '%q\n' this*
...will print out the filename in a manner the shell will accept as valid input. This might look something like:
$'this-is-my-folder200\231s-name-200\234Bob200\235'
...which you can then use as an argument to mv:
mv $'this-is-my-folder200\231s-name-200\234Bob200\235' this-is-my-folders-name-BOB
Incidentally, if your operating system works the same way mine does (when running the test above), this would explain why using single-character globs such as ? for those characters didn't work: They're actually more than one byte long each!
You can use shell globbing token ? to match any single character, so matching the smart quotes using ? should do:
mv this-is-my-folder?s-name-?Bob? new_name
Here replacing the smart quotes with ? to match the file name.
There are several possibilities.
If an initial substring of the file name ending before the first quote is unique within the directory, then you can use filename completion to help you type an appropriate command. Type "mv" (without the quotes) and the unique initial substring, then press the TAB key to request filename completion. Bash will complete the filename with the correct characters, correctly escaped.
Use a graphical file browser. Then you can select the file to rename by clicking on it. (Details of how to proceed from there depend on the browser.) If you don't have a graphical terminal and can't get one, then you may be able to do the same with a text-mode browser such as Midnight Commander.
A simple glob built with the ? or * wildcard should be able to match the filename
Use a more complex glob to select the filename, and perhaps others with the same problem. Maybe something like *[^a-zA-Z0-9-]* would do. Use a pattern substitution to assign a new name. Something like this:
for f in *[^a-zA-Z0-9-]*; do
mv "$f" "${f//[^a-zA-Z0-9-]/}"
done
The substitution replaces all appearances of a characters that are not decimal digits, appercase or lowercase Latin letters, or hyphens with nothing (i.e. it strips them). Do take care before you use this, though, to make sure you're not going to make more changes than you intend to do.

How to remove part of file names between periods?

I would like to rename many files in this format
abc.123.fits
abcd.1234.fits
efg.12.fits
to this format
abc.fits
abcd.fits
efg.fits
I tried the rename function, but since the part I'm trying to replace is not the same in all files, it did not work. I am using Linux.
for f in *; do mv "$f" "${f%%.*}.${f##*.}"; done`
${f%%.*} removes everything after the first period, including the period. ${f##*.} removes everything before the last period, including the period (i.e. it gets the file extension). Concatenating these two, with a period between them, gives you the desired result.
You can change the * to a more restrictive pattern such as *.fits if you don't want to rename all files in the current directory. The quotes around the parameters to mv are necessary if any filenames contain whitespace.
Many other variable substitution expressions are available in bash; see a reference such as TLDP's Bash Parameter Substitution for more information.

What does the operator colon in the satement "export variable=lib:/dev/input/event0" mean in linux environment??

first time see such statement by exporting a variable. How to use it and what does it mean?
The : character itself doesn't mean anything on its own. An environment variable is just that - a variable, either unset or containing some value. The value is then used by another program, so what the : means depends on what program is using the variable.
Often it is used as a separator, as with the $PATH variable - you list various directories you want checked when you execute a command in a shell without specifying a full path (eg, /bin:/usr/bin:/usr/sbin - each directory is checked).
In the example you give, lib: looks like it might be a prefix of some sort. But in the end, it really depends on what will be using the variable.

Replace pwd with USER in a file

I know that this is quite an easy thing for any advanced Vim programmer, but I have been trying to find a solution for a couple of hours now.
In my results file, there are certain lines like:
/Users/name/Project/Task1/folder1 : INFO : Random Info message
Here, /Users/name/Project/Task1/folder1 is my pwd i.e present working directory.
I want to replace all the occurrences of my pwd above in the file with 'USER'. How can I do that?
:%s#/Users/name/Project/Task1/folder1#USER#g
or
:%s#<C-r>=getcwd()<CR>#USER#g
If I understand you correctly you can simply use the search and replace functionality and escape the / character like this:
:%s/\/Users\/name\/Project\/Task1\/folder1/USER/
If you need to replace multiple current working directories (and thus want to have the pwd to be dynamic) it is probably easier to use something like sed:
sed "s~$(pwd)~USER~" < file
Note that the ~ is used as a delimiter for the command instead of the /, this way we do not need to escape the / in the path.

How to escape colon (:) in $PATH on UNIX?

I need to parse the $PATH environment variable in my application.
So I was wondering what escape characters would be valid in $PATH.
I created a test directory called /bin:d and created a test script called funny inside it. It runs if I call it with an absolute path.
I just can't figure out how to escape : in $PATH I tried escaping the colon with \ and wrapping it into single ' and double " quotes. But always when I run which funny it can't find it.
I'm running CentOS 6.
This is impossible according to the POSIX standard. This is not a function of a specific shell, PATH handling is done within the execvp function in the C library. There is no provision for any kind of quoting.
This is the reason why including certain characters (anything not in the "portable filename character set" - colon is specifically called out as an example.) is strongly recommended against.
From SUSv7:
Since <colon> is a separator in this context, directory names that might be used in PATH should not include a <colon> character.
See also source of GLIBC execvp. We can see it uses the strchrnul and memcpy functions for processing the PATH components, with absolutely no provision for skipping over or unescaping any kind of escape character.
Looking at the function
extract_colon_unit
it seems to me that this is impossible. The : is unconditionally and
inescapably used as the path separator.
Well, this is valid at least for bash. Other shells may vary.
You could try mounting it
mount /bin:d /bind
PATH=/bind
According to http://tldp.org/LDP/abs/html/special-chars.html single quotes should preserve all special characters, so without trying it, I would think that '/bin:d' would work (with)in $PATH.

Resources