how to specify path with space inside file in linux - linux

cat ~/.last_dir
/mnt/c/Users/Administrator/OneDrive/Desktop/main project/backup/main project 2
cd cat ~/.last_dir
-bash: cd: too many arguments
I tried using backslash inside the file
/mnt/c/Users/Administrator/OneDrive/Desktop/main\ project/backup/main\ project\ 2
Still same error

You need to quote the results of expanding cat ...:
cd "$(cat ~/.last_dir)"

cd "$(<~/.last_dir)"
First, put quotes around the $(...) to make the space part of the filename.
Second, $(<...) is a bash construct that reads the file directly without executing cat, but is not entirely portable.
For a more generic, less bash-specific version, use Maxim's solution.

just put quotation marks around your path:
"/mnt/c/Users/Administrator/OneDrive/Desktop/main project/backup/main project 2"
this should work for most cases

Related

"Cat" into multiple files using brace expansion

I am quite new to bash and trying to type some text into multiple files with a single command using brace expansion.
I tried: cat > file_{1..100} to write into 100 files some text that I will type in the terminal. I get the following error:
bash: file_{1..100}: ambiguous redirect
I also tried: cat > "file_{1..100}" but that creates a singe file named: file_{1..100}.
I tried: cat > `file_{1..100}` but that gives the error:
file_1: command not found
How can I achieve this using brace expansion? Maybe there are other ways using other utilities and/or pipelines. But I want to know if that is possible using only simple brace expansion or not.
You can't do this with cat alone. It only writes its output to its standard output, and that single file descriptor can only be associated with a single file.
You can however do it with tee file_{1..100}.
You may wish to consider using tee file_{01..100} instead, so that the filenames are zero-padded to all have the same width: file_001, file_002, ... This has the advantage that lexicographic order will agree with numerical order, and so ls, *, etc, will process them in numerical order. Without this, you have the situation that file_2 comes after file_10 in lexicographic order.
target could be only a pipe, not a multiple files.
If you want redirect output to multiple files, use tee
cat | tee file_{1..100}
Don't forget to check man tee, for example if you want to append to the files, you should add -a option (tee -a file_{1..100})
This types the string or text into file{1..4}
echo "hello you just knew me by kruz" > file{1..4}
Use to remove them
rm file*

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'

Read filename with * shell bash

I'am new in Linux and I want to write a bash script that can read in a file name of a directory that starts with LED + some numbers.(Ex.: LED5.5.002)
In that directory there is only one file that will starts with LED. The problem is that this file will every time be updated, so the next time it will be for example LED6.5.012 and counting.
I searched and tried a little bit and came to this solution:
export fspec=/home/led/LED*
LedV=`basename $fspec`
echo $LedV
If I give in those commands one by one in my terminal it works fine, LedV= LED5.5.002 but if i run it in a bash scripts it gives the result: LedV = LED*
I search after another solution:
a=/home/led/LED*
LedV=$(basename $a)
echo $LedV
but here again the same, if i give it in one by one it's ok but in a script: LedV = LED*.
It's probably something small but because of my lack of knowledge over Linux I cannot find it. So can someone tell what is wrong?
Thanks! Jan
Shell expansions don't happen on scalar assignments, so in
varname=foo*
the expansion of "$varname" will literally be "foo*". It's more confusing when you consider that echo $varname (or in your case basename $varname; either way without the double quotes) will cause the expansion itself to be treated as a glob, so you may well think the variable contains all those filenames.
Array expansions are another story. You might just want
fspec=( /path/LED* )
echo "${fspec[0]##*/}" # A parameter expansion to strip off the dirname
That will work fine for bash. Since POSIX sh doesn't have arrays like this, I like to give an alternative approach:
for fspec in /path/LED*; do
break
done
echo "${fspec##*/}"
pwd
/usr/local/src
ls -1 /usr/local/src/mysql*
/usr/local/src/mysql-cluster-gpl-7.3.4-linux-glibc2.5-x86_64.tar.gz
/usr/local/src/mysql-dump_test_all_dbs.sql
if you only have 1 file, you will only get 1 result
MyFile=`ls -1 /home/led/LED*`

how to use a string as an argument in an for ... in ... statement in linux shell

I'm familiar with the structure of
for file in foo/folder\ with\ spaces/foo2/*.txt
do
#do some stuff...
done
However, I want to put foo/folder with spaces/foo2/*.txt into a variable and then use it. Something like this:
myDirectory="foo/folder with spaces/foo2/*.txt"
for file in $myDirectory
do
# do some stuff
done
But what I've written here doesn't work, and it won't work even if I do
myDirectory="food/folder\ with\ spaces/foo2/*.txt"
or
for file in "$myDirectory" ...
Any help? is this even possible?
don't parse ls
# your files are expanded here
# note lack of backslashes and location of quotes
myfiles=("food/folder with spaces/foo2/"*.txt)
# iterate over the array with this
for file in "${myfiles[#]}"; do ...
Parsing ls is a bad idea, instead just do the shell globbing outside of the quotes.
You could also do:
$mydir="folder/with spaces"
for file in "$mydir"/*; do
...
done
Also look into how find and xargs works. Many of these sort of problems can be solved using those. Look at the -print0 and -0 options in particular if you want to be safe.
Try using the ls command in the for loop. This works for me:
for file in `ls "$myDirectory"`

linux batch rename directories and strip # character from name

i have a directory with a lot of subdirectories with a # infront of them:
#adhasdk
#ad18237
I want to rename them all and remove the # caracter
I tried to do:
rename -n `s/#//g` *
but didn't seem to work.
-bash: s/#//g: No such file or directory
Any ideas on this.
Thanks
Just use
$ rename 's/^#//' *
use -n just to check that what you think it would happen really happens.
In you example you have the clue about the wrong quotes used (backticks) in the error message
-bash: s/#//g: No such file or directory
bash is trying to execute a command named s/#//g.
No that using g (global) and not anchoring the regular expression you will replace any #, not just the one in the first position.
I don't know whether it's just a typo when you typed it here, but that "rename" command should work if:
you leave off the "-n" and
you quote the substitution with regular single-quotes and not back-quotes
The "-n" tells it to not really do anything. The back-quotes are just wrong (they mean something but not what you want here).
The problem is that you use backticks (`). You should use normal quotes:
rename -n 's/#//g' *
for DIR in \#*/
do
echo mv "$DIR" "${DIR/#\#/}"
done
I had to rename all folders inside a given folder. Each folder name had some text inside round braces. The following command removed the round braces from all folder names:
rename 's/(.+)//' *
Some distros doesn't support regexp in rename. You have to install prename. Even more, sometimes you can't install prename and you have to install gprename to have binary prename.
If you have 'prename' then just change backtick character " ` " to single quote and everything should work.
So the solution should be:
prename -n 's/#//g' *
or
prename -n 'y/#//' *

Resources