Bash: use an alias in a filepath - bash

I cannot seem to figure out how to use an alias for a filename in a path. For example:
alias a="ls /tmp/ -tr | tail -n 1"
cat /tmp/a
The alias gives me the name of the most recent file written in /tmp/. Then I try to cat that file and I get cat: /tmp/a: No such file or directory.
When I just type a I get the right thing, for instance some_log_I_just_wrote_to.log.
Obviously what I want is for cat /tmp/a to be translated into cat /tmp/some_log_I_just_wrote_to.log so that I can see the log.
Any ideas on what the right way to do this is? I sometimes get tangled up in bash with when to use aliases and symlinks and just plain variables, etc.
Thanks!

Create the alias with
alias a='ls /tmp/ -tr | tail -n 1'
Use the alias with cat
cat $(echo -n /tmp/ && a)

Related

Why is this bash script not changing path?

I wrote a basic script which changes the directory to a specific path and shows the list of folders, but my script shows the list of files of the current folder where my script lies instead of which I specify in script.
Here is my script:
#!/bin/bash
v1="$(ls -l | awk '/^-/{ print $NF }' | rev | cut -d "_" -f2 | rev)"
v2=/home/PS212-28695/logs/
cd $v2 && echo $v1
Does any one knows what I am doing wrong?
Your current script makes no sense really. v1 variable is NOT a command to execute as you expect, but due to $() syntax it is in fact output of ls -t at the moment of assignment and that's why you have files from current directory there as this is your working directory at that particular moment. So you should rather be doing ordinary
ls -t /home/PS212-28695/logs/
EDIT
it runs but what if i need to store the ls -t output to variable
Then this is same syntax you already had, but with proper arguments:
v1=$(ls -t /home/PS212-28695/logs/)
echo ${v1}
If for any reason you want to cd then you have to do that prior setting v1 for the same reason I explained above.

Can I use a variable in a file path in bash? If so, how?

I'm trying to write a small shell script to find the most recently-added file in a directory and then move that file elsewhere. If I use:
ls -t ~/directory | head -1
and then store this in the variable VARIABLE_NAME, why can't I then then move this to ~/otherdirectory via:
mv ~/directory/$VARIABLE_NAME ~/otherdirectory
I've searched around here and Googled, but there doesn't seem to be any information on using variables in file paths? Is there a better way to do this?
Edit: Here's the portion of the script:
ls -t ~/downloads | head -1
read diags
mv ~/downloads/$diags ~/desktop/testfolder
You can do the following in your script:
diags=$(ls -t ~/downloads | head -1)
mv ~/downloads/"$diags" ~/desktop/testfolder
In this case, diags is assigned the value of ls -t ~/downloads | head -1, which can be called on by mv.
The following commands
ls -t ~/downloads | head -1
read diags
are probably not what you intend: the read command does not receive its input from the command before. Instead, it waits for input from stdin, which is why you believe the script to 'hang'. Maybe you wanted to do the following (at least this was my first erroneous attempt at providing a better solution):
ls -t ~/downloads | head -1 | read diags
However, this will (as mentioned by alvits) also not work, because each element of the pipe runs as a separate command: The variable diags therefore is not part of the parent shell, but of a subprocess.
The proper solution therefore is:
diags=$(ls -t ~/downloads | head -1)
There are, however, further possible problems, which would make the subsequent mv command fail:
The directory might be empty.
The file name might contain spaces, newlines etc.

How to get oldest file in ftp directory using bash script

I have a working script that get all file list in a ftp directory and sae it in a local file with this:
curl -s -l ftp://username:password#ftpserver.com/directory/ > source.txt
Now, I need to sort this result by creation date instead of name. I only need to write the oldest file name in the source.txt file. Is it possible?
Thank you.
To get filename (and further informations) about file with oldest modification date in a given directory with lftp:
Example:
lftp -u anonymous,anonymous -e "ls -t; quit" ccrma-ftp.stanford.edu/pub | tail -n 1
Finally this script Works for me: lftp -u user,password -e "cls --sort=date; quit" ftpserveraddress/Folder 2> /dev/null | tail -n 1

cat command in unix shell script

I have 2 lines of code
1) With the following code:
for i in `ls *.properties`; do cat $i; done
I get the error:
cat: file_name.properties: No such file or directory.
2) On the other hand:
for i in *.properties; do cat $i; done
Works fine!
I thought both were the same. Can someone help me understand the difference between the two? Using bash shell.
What does the following command print?
cat -v <<< `ls *.properties`
I guess the problem is, that ls is a strange alias, e.g. something like
ls='ls --color'
Edit: I have seen this before. The alias should be: alias ls='ls --color=auto'
Most probably there is a directory which matches *.properties. Then ls will output the files in this directory without the directory name. Then the cat will not find the given filename.
So please check, whether file_name.properties is in the actual directory or in some subdirectory.
EDIT
To reproduce the problem you can try this:
# cd /tmp
# mkdir foo.properties
# touch foo.properties/file_name.properties
# for i in `ls *.properties`; do cat $i; done
cat: file_name.properties: No such file or directory

Inline comments for Bash?

I'd like to be able to comment out a single flag in a one-line command. Bash only seems to have from # till end-of-line comments. I'm looking at tricks like:
ls -l $([ ] && -F is turned off) -a /etc
It's ugly, but better than nothing. Is there a better way?
The following seems to work, but I'm not sure whether it is portable:
ls -l `# -F is turned off` -a /etc
My preferred is:
Commenting in a Bash script
This will have some overhead, but technically it does answer your question
echo abc `#put your comment here` \
def `#another chance for a comment` \
xyz etc
And for pipelines specifically, there is a cleaner solution with no overhead
echo abc | # normal comment OK here
tr a-z A-Z | # another normal comment OK here
sort | # the pipelines are automatically continued
uniq # final comment
How to put a line comment for a multi-line command
I find it easiest (and most readable) to just copy the line and comment out the original version:
#Old version of ls:
#ls -l $([ ] && -F is turned off) -a /etc
ls -l -a /etc
$(: ...) is a little less ugly, but still not good.
Here's my solution for inline comments in between multiple piped commands.
Example uncommented code:
#!/bin/sh
cat input.txt \
| grep something \
| sort -r
Solution for a pipe comment (using a helper function):
#!/bin/sh
pipe_comment() {
cat -
}
cat input.txt \
| pipe_comment "filter down to lines that contain the word: something" \
| grep something \
| pipe_comment "reverse sort what is left" \
| sort -r
Or if you prefer, here's the same solution without the helper function, but it's a little messier:
#!/bin/sh
cat input.txt \
| cat - `: filter down to lines that contain the word: something` \
| grep something \
| cat - `: reverse sort what is left` \
| sort -r
Most commands allow args to come in any order. Just move the commented flags to the end of the line:
ls -l -a /etc # -F is turned off
Then to turn it back on, just uncomment and remove the text:
ls -l -a /etc -F
How about storing it in a variable?
#extraargs=-F
ls -l $extraargs -a /etc
If you know a variable is empty, you could use it as a comment. Of course if it is not empty it will mess up your command.
ls -l ${1# -F is turned off} -a /etc
ยง 10.2. Parameter Substitution
For disabling a part of a command like a && b, I simply created an empty script x which is on path, so I can do things like:
mvn install && runProject
when I need to build, and
x mvn install && runProject
when not (using Ctrl + A and Ctrl + E to move to the beginning and end).
As noted in comments, another way to do that is Bash built-in : instead of x:
$ : Hello world, how are you? && echo "Fine."
Fine.
It seems that $(...) doesn't survive from ps -ef.
My scenario is that I want to have a dummy param that can be used to identify the very process. Mostly I use this method, but the method is not workable everywhere. For example, python program.py would be like
mkdir -p MyProgramTag;python MyProgramTag/../program.py
The MyProgramTag would be the tag for identifying the process started.

Resources