Can't exec an alias or function [closed] - bash

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have an alias that I would like to be able to call into with exec but I'm not sure how to make it work. The example is simplified but I think enough to highlight the issue. Changing the alias to a function doesn't work either. Calling the alias/function directly does work, just not when using exec.
The command I am using is,
alias myalias="ls -lah /tmp"
exec myalias
But it fails with something similar to the following,
bash: exec: myalias: not found
Is it just not possible to do this using exec?

You don't have any functions or aliases in your example, but if you did have an alias, you could have aliased exec itself to exec it:
#!/bin/bash -i
# Define an alias
alias myalias="ls -lah /tmp"
# Allow `exec` to work for aliases
alias exec='exec '
# This now works as expected
exec myalias
Here's man bash for why this works:
Aliases allow a string to be substituted for a word when it is used as
the first word of a simple command. [...]
If the last character of the alias value is a blank, then the next command word following the alias is also checked for alias expansion.

An alias definition:
$ alias myalias='ls -lah /tmp'
Invoking the alias:
$ myalias
total 36M
drwxrwxrwt+ 1 myuser None 0 Nov 30 16:01 ./
drwxr-xr-x+ 1 myuser None 0 Nov 6 11:29 ../
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 a
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 b
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 c
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 d
-rw-r--r-- 1 myuser mygroup 36M Jun 6 17:29 giga.txt
drwx------+ 1 myuser mygroup 0 Mar 8 2020 runtime-makaakd/
drwx------+ 1 myuser mygroup 0 Nov 8 16:10 tmp.8yl3CJgSn2/
-rw------- 1 myuser mygroup 66 Oct 14 21:49 tmp.BeEvxDpHGr
... snip ...
As is (assigning string to a variable):
$ myalias="ls -lah /tmp"
'Running' the variable:
$ ${myalias}
total 36M
drwxrwxrwt+ 1 myuser None 0 Nov 30 16:01 ./
drwxr-xr-x+ 1 myuser None 0 Nov 6 11:29 ../
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 a
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 b
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 c
-rw-r--r-- 1 myuser mygroup 0 Oct 10 11:31 d
-rw-r--r-- 1 myuser mygroup 36M Jun 6 17:29 giga.txt
drwx------+ 1 myuser mygroup 0 Mar 8 2020 runtime-makaakd/
drwx------+ 1 myuser mygroup 0 Nov 8 16:10 tmp.8yl3CJgSn2/
-rw------- 1 myuser mygroup 66 Oct 14 21:49 tmp.BeEvxDpHGr
... snip ...

Related

Is there a way to remove the owner's read permissions on a file in macOS?

Is there any way to take away the owner's permission to read a file in macOS? I know there's no reason to do this but I have to for school and I can't find an answer anywhere. Removing my write permission works fine but when I try to remove my read permission it automatically give me my read and write permissions back. As you can see in the console when I use chmod -v -v (extra verbose) it shows the correct permissions it should be changed to but then when checking afterwards they havent changed into that...
thijs#Thijss-MacBook-Air-2 week6 % ls -l
total 16
-rw----r-- 1 thijs staff 12 Oct 11 21:10 greeting.txt
-rw-r--r-- 1 thijs staff 0 Oct 11 21:10 hello.txt
-rw------- 1 thijs staff 15 Oct 11 21:11 weather.txt
thijs#Thijss-MacBook-Air-2 week6 % chmod -v -v u-w weather.txt
weather.txt: 0100600 [-rw------- ] -> 0100400 [-r-------- ]
thijs#Thijss-MacBook-Air-2 week6 % ls -l
total 16
-rw----r-- 1 thijs staff 12 Oct 11 21:10 greeting.txt
-rw-r--r-- 1 thijs staff 0 Oct 11 21:10 hello.txt
-r-------- 1 thijs staff 15 Oct 11 21:11 weather.txt
thijs#Thijss-MacBook-Air-2 week6 % chmod -v -v u-r weather.txt
weather.txt: 0100400 [-r-------- ] -> 0100000 [---------- ]
thijs#Thijss-MacBook-Air-2 week6 % ls -l
total 16
-rw----r-- 1 thijs staff 12 Oct 11 21:10 greeting.txt
-rw-r--r-- 1 thijs staff 0 Oct 11 21:10 hello.txt
-rw------- 1 thijs staff 15 Oct 11 21:11 weather.txt

How to touch files with different names and different date created

I am trying to create files with different date created:
$ touch -t 20{11..15}01120000 file_{1..5}.txt
$ ls -al
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 201201120000
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 201301120000
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 201401120000
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 201501120000
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 file_1.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 file_2.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 file_3.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 file_4.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 file_5.txt
As you can see all file's dates created are 2011 Jan 12 0.
How can I create files with a different year?
# this is what I want
-rw-r--r-- 1 shinokada staff 0 Jan 12 2011 file_1.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2012 file_2.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2013 file_3.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2014 file_4.txt
-rw-r--r-- 1 shinokada staff 0 Jan 12 2015 file_5.txt
What is the best way?
touch command allows you to enter one one timestamp using -t option.
A traditional for-loop would be better:
for i in {1..5}; do touch -t 201${i}01120000 file_$i.txt; done
Shortly, but keeping filenumbers and years as separated variables
I think this is more readable, but...
Care about timezone!
filenum=1
for year in {2011..2015};do
TZ=UTC touch -t ${year}12312345 file-$((filenum++))
done
Then if you look about this, using a different timezone:
(Note that created date was Dec 31, 23h45')
TZ=UTC-1 ls -ltr
-rw-r--r-- 1 user user 0 jan 1 2012 file-1
-rw-r--r-- 1 user user 0 jan 1 2013 file-2
-rw-r--r-- 1 user user 0 jan 1 2014 file-3
-rw-r--r-- 1 user user 0 jan 1 2015 file-4
-rw-r--r-- 1 user user 0 jan 1 2016 file-5
Could you please try following, I would go with following approach with a for loop. Where I am providing year, number of files which needed, output file's initial value and same time value for all output files so that we can manage it in for loop.
cat script.bash
year=2011
numberoffiles="10"
time="01120000"
outputfileInitials="file"
nameSequence="1"
for ((i = 1 ; i <= numberoffiles ; i++ ));
do
touch -t $year$time "${outputfileInitials}_$nameSequence.txt"
(( nameSequence = nameSequence + 1 ))
(( year = year + 1 ))
done

Can I change the modified date, just the year, of a file or all files?

Can I change the modified date, just the year, of a file or all files?
I have been looking here which lead me to touch.
$ ls -l *.txt
-rw-r--r-- 1 kevin.smith mkpasswd 3319 Nov 21 2017 adjectives.txt
-rw-r--r-- 1 kevin.smith mkpasswd 25562 Aug 11 2015 checklist.txt
-rwxr-xr-x 1 kevin.smith mkpasswd 11347 May 9 14:28 cw_text.txt
-rw-r--r-- 1 kevin.smith mkpasswd 9260 May 9 14:31 cw_text2.txt
-rw-r--r-- 1 kevin.smith mkpasswd 4786 May 9 14:38 cw_text3.txt
-rw-r--r-- 1 kevin.smith mkpasswd 390 Jun 25 2014 Delete_log.txt
-rw-r--r-- 1 kevin.smith mkpasswd 6891 Jul 27 2015 log.txt
-rw-r--r-- 1 kevin.smith mkpasswd 53828 Jan 17 2017 pin1.txt
-rw-r--r-- 1 kevin.smith mkpasswd 39412 Jan 17 2017 pip2.txt
-rw-r--r-- 1 kevin.smith mkpasswd 167 Dec 5 2015 romeo.txt
$ touch -t 2018* *.txt
Expected Output: Would have only the year changed to 2018
$ ls -l *.txt
-rw-r--r-- 1 kevin.smith mkpasswd 3319 Nov 21 2018 adjectives.txt
-rw-r--r-- 1 kevin.smith mkpasswd 25562 Aug 11 2018 checklist.txt
-rwxr-xr-x 1 kevin.smith mkpasswd 11347 May 9 14:28 cw_text.txt
-rw-r--r-- 1 kevin.smith mkpasswd 9260 May 9 14:31 cw_text2.txt
-rw-r--r-- 1 kevin.smith mkpasswd 4786 May 9 14:38 cw_text3.txt
-rw-r--r-- 1 kevin.smith mkpasswd 390 Jun 25 2018 Delete_log.txt
-rw-r--r-- 1 kevin.smith mkpasswd 6891 Jul 27 2018 log.txt
-rw-r--r-- 1 kevin.smith mkpasswd 53828 Jan 17 2018 pin1.txt
-rw-r--r-- 1 kevin.smith mkpasswd 39412 Jan 17 2018 pip2.txt
-rw-r--r-- 1 kevin.smith mkpasswd 167 Dec 5 2018 romeo.txt
ls -l file.txt; touch -t "$(date -d "#$(stat -c '%Y' file.txt)" "+2020%m%d%H%M")" file.txt; ls -l file.txt
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-rw-r--r-- 1 jackman jackman 0 Oct 23 16:47 file.txt
-rw-r--r-- 1 jackman jackman 0 Oct 23 2020 file.txt
You'll need to use a for loop to iterate over the files, and query/update the mtime one-by-one

MacOS Command Line - Create folder with files at once

Is it possible to write a command that will create a new directory with name passed as argument 'MyFolder' (for example) and will create four files with the same name (as part):
MyFolder.js
MyFolder.css
MyFolder.test.js
README.md
(using mkdir / touch / echo ...)
Main problem - one line command
This one-liner function should do the work:
$ function mkdir_and_files() { mkdir "${1}"; touch ${1}/${1}.js; touch ${1}/${1}.css; touch ${1}/${1}.test.js; touch ${1}/README.md; }; mkdir_and_files "MyFolder" ;
$ ls -latrh MyFolder/
total 0
drwxrwxrwt 15 root wheel 480B Aug 19 18:58 ..
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 MyFolder.js
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 MyFolder.css
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 MyFolder.test.js
-rw-r--r-- 1 user wheel 0B Aug 19 18:58 README.md
drwxr-xr-x 6 user wheel 192B Aug 19 18:58 .
Try this:
populate_dir() { mkdir "$1"; touch "$1/$1".{js,css,test.js} "$1/README.md"; }
populate_dir MyFolder

TCL/Expect - exec - how to execute program with parameters

I am experimenting with TCL command exec in tclsh and here are my results:
% set show_me_dir "ls"
ls
% exec $show_me_dir
VboxSharedFolder
% set show_me_dir "ls -la"
ls -la
% exec $show_me_dir
couldn't execute "ls -la": no such file or directory
% set show_me_dir {ls -la}
ls -la
% exec $show_me_dir
couldn't execute "ls -la": no such file or directory
% ls -la
total 141
d---------+ 1 wakatana Domain Users 0 Jan 22 19:12 .
d---------+ 1 wakatana Domain Users 0 Apr 16 2014 ..
----------+ 1 wakatana Domain Users 20214 Jan 23 18:43 .bash_history
----------+ 1 wakatana Domain Users 1494 Apr 15 2014 .bash_profile
----------+ 1 wakatana Domain Users 7593 Jan 22 19:03 .bashrc
d---------+ 1 wakatana Domain Users 0 Jan 15 14:56 VboxSharedFolder
%
Can somebody please explain how can I execute command with arguments?
Edit:
The following example from Expanding a list of parameters in Tcl and eval article was big eye opener of what is going on here:
The variable $action is only expanded into the string "piemiddle apple" AFTER the command line has been split into its individual parameters:
% set action {piemiddle apple}
% set $action
can't read "piemiddle apple": no such variable
Result: set command "sees" one argument, equivalent to:
% set {piemiddle apple}
The expand operator allows you to specify that a variable is to be expanded BEFORE the command line is split into individual parameters:
% set action {piemiddle apple}
% set {*}$action
apple
Result: set command "sees" two arguments, equivalent to:
% set piemiddle apple
In earlier versions of Tcl, the eval command was the recommended alternative and it remains available today.
% set action {piemiddle apple}
% eval set $action
apple
Another examples which proves functionality of expansion operator:
% set {*}"name Linus"
Linus
% puts $name
Linus
%
%
% set distro Unbuntu
Unbuntu
% set {*}"linux $distro"
Unbuntu
% puts $linux
Unbuntu
%
%
Finally the discovery that exec needs command as it's first argument and first command option as it's second argument etc.
% exec "ls" "-la"
total 137
d---------+ 1 wakatana Domain Users 0 Jan 22 19:12 .
d---------+ 1 wakatana Domain Users 0 Apr 16 2014 ..
----------+ 1 wakatana Domain Users 20214 Jan 23 18:43 .bash_history
----------+ 1 wakatana Domain Users 1494 Apr 15 2014 .bash_profile
----------+ 1 wakatana Domain Users 7593 Jan 22 19:03 .bashrc
d---------+ 1 wakatana Domain Users 0 Jan 15 14:56 VboxSharedFolder
%
%
% exec "ls -la"
couldn't execute "ls -la": no such file or directory
The safest way to build a command for exec is to use Tcl's list. For example:
% set tcl_version
8.5
% set cmd [list ls -l tmp]
ls -l tmp
% eval exec $cmd
total 32
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 file.txt
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 foo-1.dat
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 foo-2.dat
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 foo-3.dat
% exec {*}$cmd
total 32
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 file.txt
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 foo-1.dat
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 foo-2.dat
-rw-r--r-- 1 pynexj staff 1176 Jan 23 23:24 foo-3.dat
%
Note that {*} is a new syntax of Tcl 8.5 which can help reduce the uses of eval.
As example for ls command you can do:
exec {*}ls -lsa {*}[glob *.cpp]
Please have a look at What does {*} do in TCL?

Resources