Hello I am trying to establish in the following alias with gitbash and cannot :
alias dirpwd='$(`pwd | xargs dirname | xargs basename -a`)' && echo -e $dirpwd;
The output is :
bash: c: command not found
Why?
Thanks all !!
What happens:
Backticks and $() work in the same way. The command inside them gets executed and the resulting output is treated as if you typed it in directly.
Assume you are in /top/c/bottom.
The part pwd | xargs dirname | xargs basename -a inside the backticks has output c.
Bash replaces the backtick part with its output, resulting in the command $(c).
Now bash tries to execute the command inside $(...) but c is not a command, hence the error bash: c: command not found.
First Fix:
I guess you just want to write
alias dirpwd="pwd | xargs dirname | xargs basename -a"
Bug:
There is a hidden bug. xargs splits at spaces and may pass multiple arguments to dirname and basename.
Example: Assume you you are in /top/a b c/. xarg creates the following command and output
dirname "/top/a" "b" "c/"
/top
.
.
Second Fix:
Use $() instead of xargs.
alias dirpwd='basename "$(dirname "$PWD")"'
Try how an solution is :
alias dirpwd="pwd | xargs dirname | xargs basename -a"
Related
Saying that I have two files t1 and t2, they have the same content: abc.
Now I want to delete all files, who contains the string abc.
So I tried to execute the command: grep -rl abc . | rm but it doesn't work.
Then I add xargs: grep -rl abc . | xargs rm and it works.
I can't understand clearly what xargs did.
grep puts the output as stdout. But rm cannot process data from stdin (the pipe links both).
You want instead, that the output of grep is put as argument of rm. So xargs command "convert" stdin into arguments of xargs first argument, and it call the command (the first argument).
As alternative, you could do
rm `grep -rl abc .`
or
rm $(grep -rl abc .)
But xargs handles well also the case where there are too many arguments for a single call of the command. The above command will give you shell error (argument string too long).
rm doesn't read from standard input (except when prompting, like with -i) but takes its arguments on the command line. That's what xargs does for you: read things from standard input and give them to rm as arguments.
Example with echo:
$ (echo a; echo b; date) | xargs echo
a b tor 12 apr 2018 14:18:50 CEST
I'm starting in the shell script.I'm need to make the checksum of a lot of files, so I thought to automate the process using an shell script.
I make to scripts: the first script uses an recursive ls command with an egrep -v that receive as parameter the path of file inputed by me, these command is saved in a ambient variable that converts the output in a string, follow by a loop(for) that cut the output's string in lines and pass these lines as a parameter when calling the second script; The second script take this parameter and pass they as parameter to hashdeep command,wich in turn is saved in another ambient variable that, as in previous script,convert the output's command in a string and cut they using IFS,lastly I'm take the line of interest and put then in a text file.
The output is:
/home/douglas/Trampo/shell_scripts/2016-10-27-001757.jpg: No such file
or directory
----Checksum FILE: 2016-10-27-001757.jpg
----Checksum HASH:
the issue is: I sets as parameter the directory ~/Pictures but in the output error they return another directory,/home/douglas/Trampo/shell_scripts/(the own directory), in this case, the file 2016-10-27-001757.jpg is in the ~/Pictures directory,why the script is going in its own directory?
First script:
#/bin/bash
arquivos=$(ls -R $1 | egrep -v '^d')
for linha in $arquivos
do
bash ./task2.sh $linha
done
second script:
#/bin/bash
checksum=$(hashdeep $1)
concatenado=''
for i in $checksum
do
concatenado+=$i
done
IFS=',' read -ra ADDR <<< "$concatenado"
echo
echo '----Checksum FILE:' $1
echo '----Checksum HASH:' ${ADDR[4]}
echo
echo ${ADDR[4]} >> ~/Trampo/shell_scripts/txt2.txt
I think that's...sorry about the English grammatic errors.
I hope that the question has become clear.
Thanks ins advanced!
There are several wrong in the first script alone.
When running ls in recursive mode using -R, the output is listed per directory and each file is listed relative to their parent instead of full pathname.
ls -R doesn't list the directory in long format as implied by | grep -v ^d where it seems you are looking for files (non directories).
In your specific case, the missing file 2016-10-27-001757.jpg is in a subdirectory but you lost the location by using ls -R.
Do not parse the output of ls. Use find and you won't have the same issue.
First script can be replaced by a single line.
Try this:
#!/bin/bash
find $1 -type f -exec ./task2.sh "{}" \;
Or if you prefer using xargs, try this:
#!/bin/bash
find $1 -type f -print0 | xargs -0 -n1 -I{} ./task2.sh "{}"
Note: enclosing {} in quotes ensures that task2.sh receives a complete filename even if it contains spaces.
In task2.sh the parameter $1 should also be quoted "$1".
If task2.sh is executable, you are all set. If not, add bash in the line so it reads as:
find $1 -type f -exec bash ./task2.sh "{}" \;
task2.sh, though not posted in the original question, is not executable. It has a missing execute permission.
Add execute permission to it by running chmod like:
chmod a+x task2.sh
Goodluck.
I am using the below command to find the file names and it works fine when execute from command line:
$AIX->: find . | xargs grep -l "BE00036"
./6281723219129
$AIX->:
But the same command is not working when execute from shell script(ksh):
$AIX->: ksh test.ksh
**find: bad option -l**
part of my code is:
Var="find . | xargs grep -l \"BE00036\"
print `$Var`
If you want to assign the output of a command to a variable, you can do
Var="$(find . | xargs grep -l \"BE00036\")"
print "$Var"
This below one works for me:
var=`find . | xargs grep -l 'BE00036'`
echo "$var"
How do I pipe commands and their results in Ubuntu when writing them in the terminal. I would write the following commands in sequence -
$ ls | grep ab
abc.pdf
cde.pdf
$ cp abc.pdf cde.pdf files/
I would like to pipe the results of the first command into the second command, and write them all in the same line. How do I do that ?
something like
$ cp "ls | grep ab" files/
(the above is a contrived example and can be written as cp *.pdf files/)
Use the following:
cp `ls | grep ab` files/
Well, since the xargs person gave up, I'll offer my xargs solution:
ls | grep ab | xargs echo | while read f; do cp $f files/; done
Of course, this solution suffers from an obvious flaw: files with spaces in them will cause chaos.
An xargs solution without this flaw? Hmm...
ls | grep ab | xargs '-d\n' bash -c 'docp() { cp "$#" files/; }; docp "$#"'
Seems a bit klunky, but it works. Unless you have files with returns in them I mean. However, anyone who does that deserves what they get. Even that is solvable:
find . -mindepth 1 -maxdepth 1 -name '*ab*' -print0 | xargs -0 bash -c 'docp() { cp "$#" files/; }; docp "$#"'
To use xargs, you need to ensure that the filename arguments are the last arguments passed to the cp command. You can accomplish this with the -t option to cp to specify the target directory:
ls | grep ab | xargs cp -t files/
Of course, even though this is a contrived example, you should not parse the output of ls.
I'm trying to write an alias which will jump to the descendant directory of cwd which contains a specified file (or the first find found occurrence of such a filename):
The following command combination achieves the desired result:
cd `dirname \`find -name 'MyFile.txt' | sed -n 1p\``
However, I can't seem to escape this in the correct way to create a working alias:
alias jump="cd \`dirname \\\`find -name '$1' | sed -n 1p\\\`\`"
Output:
/*
dirname: missing operand
Try `dirname --help' for more information.
bash: cd: find: No such file or directory
My logic is that backticks need escaping in a double quoted string with a single \ and I can't do \\ gets translated to a single backslash within a string, so the second nested backtick requires 1+2=3.
Any suggestions?
An alias cannot take an argument like $1. Use a function instead.
Also use $(command) for command substitution instead of backticks, as it is easier to nest.
The function would be:
jump() {
cd $(dirname $(find -name "$1" | sed -n 1p))
}
Backticks are the old form of command substitution, and you can't nest them easily. However, the new $() form does nest easily:
cd $(dirname $(find -name 'MyFile.txt' | sed -n 1p))
Backticks doesn't offer nesting. Try using command substitution which has the syntax $(..)
In your case it will be
cd $(dirname $(find /path/to/search -name 'MyFile.txt' | sed -n 1p))