Passing the most recent file in a directory to a program - bash

What would be the correct way to do the following:
$ ls -t | head -n1 | vim -
Currently, this will read the 'filename' into vim, but I'm looking at actual open that filename that's passed to it as a string. How would this be done?
Without opening the file we get:
$ ls -t | head -n1
2020-11-05.txt

You can pass it like this:
$ vim "$(ls -t | head -n1)"

Related

What does this bash command do?

What does this command do? Can it be shortened without losing functionality?
echo "abcabcabc" | sed "s/aBc/xyZ/gi;s/Z/a/;s/c/CCC/g" | xargs ls -ld
You would know what the command does if you entered it on a Mac OS terminal. It doesn't do anything but producing an error because the i in the sed command seems to be wrong or a typing error. However
echo "abcabcabc" | sed "s/aBc/xyZ/g;s/Z/a/;s/c/CCC/g" | xargs ls -ld
outputs the string abcabcabc which is used as input for the sed command which replaces aBc with xyZ, Z with a and c with CCC. This results in the string abCCCabCCCabCCC which is again input for the ls -ln command. If you had a file with the name abCCCabCCCabCCC in the current directory it would be found and it's details would be shown to you, otherwise the output is
ls: abCCCabCCCabCCC: No such file or directory
If it could be shortened depends on what you really want to achieve.
echo "abcabcabc" | sed "s/c/CCC/g" | xargs ls -ld
would have the same result in this case.

Trying to write a shell script to move most recent file from downloads to another folder

I am trying to write a script that will find the most recently added item from my downloads folder and move to to another folder. I'm close but stuck on the final part. I'm doing this as an exercise to better learn iTerm2, not for practical reasons. I realize there are simpler ways to do this in browser.
ls -t1 /Users/name/downloads | head -n 1 | > Users/name/targetfolder
If the item is a file, you can pipe your head command to cp :
ls -t1 /Users/name/downloads | head -n 1 | xargs cp -t Users/name/targetfolder
You may also add a test to check whether the item is a file or a directory :
last=$(ls -t1 . | head -n 1)
todir=Users/name/targetfolder
[ -d $last ] && cp -r "$last" "$todir" || cp "$last" "$todir"
You are correctly finding the most recent item with:
ls -t1 /Users/name/downloads | head -n 1
However you are making mistake afer that.
What you can do is:
mv $(ls -t1 /Users/name/downloads | head -n 1) Users/name/targetfolder
Above is a standard mv command whose syntax is:
mv filename target_filename # if you are renaming a file. Or,
mv filename target_dirname # if moving the file to a different directory.
Anything command between $() is replaced by its output.
So $(ls -t1 /Users/name/downloads | head -n 1) is replaced by the most recent file.
Hence, basically, the command means mv most_recent_file Users/name/targetfolder

Error while getting disk usage of a folder in unix

I have XYZ=/opt/Ind and certain directories under /opt/Ind
I sorted the directories by : ls -t $XYZ
Then I need to get only the size of the first folder.
I tried
du -sk $(ls -t $XYZ/TAL/ | head -n 1)
It gives me this error
du: cannot access `\033[0m\033[01;34m20160525_033732\033[0m': No such file or directory
Will be glad for the help.
The problem here is that you are not using the normal ls but an alias, so that it provides you some coloured output. This way, instead of a normal name 20160525_033732 you get it with the blue colour.
$ echo -e "\033[0m\033[01;34m20160525_033732\033[0m"
20160525_033732
Just use \ls to use the original ls without any alias.
du -sk "$(\ls -t $XYZ/TAL/ | head -n 1)"
# ^
See what the alias is with:
type ls
It will probably return something like:
ls is aliased to `ls --color=always'
add --color=never to the ls so it won't colorize the output:
du -sk $(ls --color=never -t $XYZ/TAL/ | head -n 1)

Search file name using a variable and replace with another variable

I have search string in one variable ($AUD_DATE) and replace string in another variable ($YEST_DATE). I need to search file name in a folder using $AUD_DATE and then replace it with $YEST_DATE.
I tried using this link to do it but its not working with variables.
Find and replace filename recursively in a directory
shrivn1 $ AUD_DATE=140101
shrivn1 $ YEST_DATE=140124
shrivn1 $ ls *$AUD_DATE*
NULRL.PREM.DATA.CLRSFIFG.140101.dat NULRL.PREM.DATA.CLRTVEH.140101.dat
shrivn1 $ ls *$AUD_DATE*.dat | awk '{a=$1; gsub("$AUD_DATE","$YEST_DATE");printf "mv \"%s\" \"%s\"\n", a, $1}'
mv "NULRL.PREM.DATA.CLRSFIFG.140101.dat" "NULRL.PREM.DATA.CLRSFIFG.140101.dat"
mv "NULRL.PREM.DATA.CLRTVEH.140101.dat" "NULRL.PREM.DATA.CLRTVEH.140101.dat"
Actual output I need is
mv "NULRL.PREM.DATA.CLRSFIFG.140101.dat" "NULRL.PREM.DATA.CLRSFIFG.140124.dat"
mv "NULRL.PREM.DATA.CLRTVEH.140101.dat" "NULRL.PREM.DATA.CLRTVEH.140124.dat"
Thanks in advance
Approach 1
I generally create mv commands using sed and then pipe the output to sh. This approach allows me to see the commands that will be executed beforehand.
For example:
$ AUD_DATE=140101
$ YEST_DATE=140124
$ ls -1tr | grep "${AUD_DATE}" | sed "s/\(.*\)/mv \1 \1_${YEST_DATE}"
Once you are happpy with the output of the previous command;repeat it and pipe it's output to sh, like so:
$ ls -1tr | grep "${AUD_DATE}" | sed "s/\(.*\)/mv \1 \1_${YEST_DATE}" | sh
Approach 2
You could use xargs command.
ls -1tr | grep ${AUD_DATE}" | xargs -I target_file mv target_file target_file${YEST_DATE}

Don't call xargs if the previous command doesn't return anything [duplicate]

This question already has answers here:
How to ignore xargs commands if stdin input is empty?
(7 answers)
Closed 6 years ago.
I have the following command that checks if any new files are added and automatically calls svn add on all these files
svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}' | xargs svn add
But when there are no files, svn add results in a warning.
How to stop from xargs from getting called the previous command doesn't result in any values? The solution needs to work with both GNU and BSD (Mac OS X) versions of xargs.
If you're running the GNU version, use xargs -r:
--no-run-if-empty
-r
If the standard input does not contain any nonblanks, do not run the command.
Normally, the command is run once even if there is no input. This option
is a GNU extension.
http://linux.die.net/man/1/xargs
If you're using bash, another way is to just store outputs in arrays. And run svn only if the there is an output.
readarray -t OUTPUT < <(exec svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}')
[[ ${#OUTPUT[#]} -gt 0 ]] && svn add "${OUTPUT[#]}"
I ended up using this. Not very elegant but works.
svn status | grep -v "^.[ \t]*\..*" | grep "^?" && svn status | grep -v "^.[ \t]*\..*" | grep "^?" | awk '{print $2}' | xargs svn add
ls /empty_dir/ | xargs -n10 chown root # chown executed every 10 args
ls /empty_dir/ | xargs -L10 chown root # chown executed every 10 lines
ls /empty_dir/ | xargs -i cp {} {}.bak # every {} is replaced with the args from one input line
ls /empty_dir/ | xargs -I ARG cp ARG ARG.bak # like -i, with a user-specified placeholder
https://stackoverflow.com/a/19038748/1655942

Resources