Executing Linux/Unix Command From Within R Using Variables - r

I'm trying to make a call from within R to execute BASH commands, to get my feet wet:
I wanted to simply capture a listing of my current files located in a specific directory through use of the "ls -al" command. The output would be sent to text file called a01_test.txt.
The directory I would like to capture the contents of is "C:\Users\user00\a01_TEST" which is referenced as "/mnt/c/Users/user00/a01_TEST/" from a WSL Ubuntu 20.04.5 LTS perspective.
The directory contains five (5) files: file_01.txt, file_02.txt ,..., file_05.txt.
FYI, I am running R (R version 4.2.0 (2022-04-22 ucrt)) via RStudio (2022.07.1 Build 554) on Windows 11 (Version 10.0.22000 Build 22000).
I tried:
PATH_UNIX <- "/mnt/c/Users/user00/a01_TEST/"
FILENAME_TEST <-"a01_test.txt"
paste0("system(\"bash -c \'ls -al ",PATH_UNIX," >",PATH_UNIX,FILENAME_TEST,"\'\")")
However that only returned a command prompt -- nothing else:
> paste0("system(\"bash -c \'ls -al ",PATH_UNIX," >",PATH_UNIX,FILENAME_TEST,"\'\")")
[1] "system(\"bash -c 'ls -al /mnt/c/Users/user00/a01_TEST/ >/mnt/c/Users/user00/a01_TEST/a01_test.txt'\")"
>
I thought one could test the code using:
cat(print(paste0("system(\"bash -c \'ls -al ",PATH_UNIX," >",PATH_UNIX,FILENAME_TEST,"\'\")")))
which resulted in:
> cat(print(paste0("system(\"bash -c \'ls -al ",PATH_UNIX," >",PATH_UNIX,FILENAME_TEST,"\'\")")))
[1] "system(\"bash -c 'ls -al /mnt/c/Users/user00/a01_TEST/ >/mnt/c/Users/user00/a01_TEST/a01_test.txt'\")"
system("bash -c 'ls -al /mnt/c/Users/user00/a01_TEST/ >/mnt/c/Users/user00/a01_TEST/a01_test.txt'")
If I do not use variables, such as, PATH_UNIX and FILENAME_TEST and code the entire path manually, I can create a text file (a01_test.txt) giving me the desired listing of the directory's contents:
system("bash -c 'ls -al /mnt/c/Users/user00/a01_TEST > /mnt/c/Users/user00/a01_TEST/a01_test.txt'")
which results in:
> system("bash -c 'ls -al /mnt/c/Users/user00/a01_TEST > /mnt/c/Users/user00/a01_TEST/a01_test.txt'")
[1] 0
>
giving me the file called "a01_test.txt" containing the directory's contents:
total 0
drwxrwxrwx 1 user00 user00 4096 Nov 3 2022 .
drwxrwxrwx 1 user00 user00 4096 Nov 3 05:07 ..
-rwxrwxrwx 1 user00 user00 0 Nov 3 2022 a01_test.txt
-rwxrwxrwx 1 user00 user00 0 Nov 3 05:26 file_01.txt
-rwxrwxrwx 1 user00 user00 0 Nov 3 05:26 file_02.txt
-rwxrwxrwx 1 user00 user00 0 Nov 3 05:26 file_03.txt
-rwxrwxrwx 1 user00 user00 0 Nov 3 05:26 file_04.txt
-rwxrwxrwx 1 user00 user00 0 Nov 3 05:26 file_05.txt
Any assistance to make use of the variables PATH_UNIX & FILENAME_TEST to make a call to Linux/Unix to obtain a directory listing would be appreciated.

sprintf (?sprintf for further details) is a convenient way to create format strings that can subsequently be passed to system:
PATH_UNIX <- '/mnt/c/Users/user00/a01_TEST/'
FILENAME_TEST <- 'a01_test.txt'
cmdstr <- sprintf('bash -c \'ls -al %s > %s\'', PATH_UNIX, FILENAME_TEST)
message('bash command string = ', cmdstr)
system(command = cmdstr)

Expanding on the solution provided by br00t, and doing some testing, one could also use the paste0() function:
# DESIRED CMD TO BE PASSED VIA BASH
cat(paste0("system(bash -c \'ls -al ",PATH_UNIX," >",PATH_UNIX,FILENAME_TEST,"\')"))
# OUTPUT:
# system(bash -c 'ls -al /mnt/c/Users/user00/a01_TEST/ >/mnt/c/Users/user00/a01_TEST/a01_test.txt')
# PLACE DESIRED CMD IN A VAR:
cmdstr_test <- paste0("bash -c \'ls -al ",PATH_UNIX," > ",PATH_UNIX,FILENAME_TEST,"\'")
# CHECK VAR:
message('bash command string = ', cmdstr_test)
# OUTPUT:
# bash command string = bash -c 'ls -al /mnt/c/Users/user00/a01_TEST/ > /mnt/c/Users/user00/a01_TEST/a01_test.txt'
# RUN COMMAND USING system() function:
system(command = cmdstr_test)
# OUTPUT (Will get "0", if successful)
> system(command = cmdstr_test)
[1] 0
>

Related

How to find file size greater than 200 MB in unix from a directory and its sub directory

Even though I used this command I am still getting output lesser than the 200 MB as well.
Command used:
find . -type f -size +200M -exec ls -lh {} \;
Output example
-rw-r--r-- 1 dummy dummy 101K Jul 27 22:43 ./sub_dir1/sub_dir2_1/file_1
-rw-r--r-- 1 dummy dummy 158M Jul 27 22:44 ./sub_dir1/sub_dir2_1/file_2
-rw-r--r-- 1 dummy dummy 1.1G Jul 27 22:44 ./sub_dir1/sub_dir2_2/file_3
-rw-r--r-- 1 dummy dummy 11M Jul 27 22:45 ./sub_dir1/sub_dir2_2/file_4
I have figured it out.
In some of the unix versions, We can't directly use the size as it is for the find commands.
In this it occupying 512 bytes.
Hence (200000000/512) = 390625
Unix command perfected:
find . -type f -size +390625 -exec ls -lh {} \;
Now it is working as expected.

Reading file mtime in UNIX in particular format (2013-06-25 09:04:32)

hi i have this file on my UNIX box (SunOS 5.10).
-rwxr-xr-x 1 phnxep siebel 917 Feb 1 02:52 crontest.sh
Here date and time are given like Feb1 02:52.Can i just read these values in UNIX for my file ignoring the rest of the details.In the required format-:
2017-02-1 02:52
And convert them to integer values later on???Please help guys i am really stuck on this.
If you are using gnu ls, try
ls -l --time-style=full-iso
E.g.:
$ touch x
$ ls -l --time-style=full-iso x
-rw-r--r-- 1 max max 0 2017-02-06 13:18:56.498920000 +0000 x
If you are using Sun ls, try -E option, e.g. ls -E.

How to compare html files in unix

I have two folders with huge number of HTML files and I want to compare each file and how to get the diff of each file using shell script/unix commands.
Example:
Directory 1:
1.html
2.html
3.html
Directory 2:
1.html
2.html
3.html..
I want to compare 1.html in directory with 1.html in dir2, and 2.html with 2.html, and so on.
try this;
#!/bin/bash
for file in $1/*.html; do
fileName=$(basename "$file")
if [ ! -f $2/$fileName ]; then
echo $fileName " not found! in "$2
else
difLineCount=$(diff $file $2/$fileName | wc -l)
if [ $difLineCount -eq 0 ]; then
echo $file "is same " $2/$fileName;
else
echo $file "is not same " $2/$fileName "." $difLineCount "lines are different";
#diff $file $2/$fileName
fi
fi
done
for file in $2/*.html; do
fileName=$(basename "$file")
if [ ! -f $1/$fileName ]; then
echo $fileName " not found! in "$1
fi
done
Ex :
user#host:/tmp$ ./test.sh Directory_1 Directory_2
Directory_1/1.html is same Directory_2/1.html
Directory_1/2.html is same Directory_2/2.html
Directory_1/3.html is not same Directory_2/3.html . 4 lines are different
4.html not found! in Directory_2
5.html not found! in Directory_1
user#host:/tmp$ ls -alrt Directory_1/
total 20
-rw-rw-r-- 1 user user 6 Ağu 11 13:28 1.html
-rw-rw-r-- 1 user user 6 Ağu 11 13:28 2.html
-rw-rw-r-- 1 user user 6 Ağu 11 13:28 3.html
-rw-rw-r-- 1 user user 0 Ağu 11 13:41 4.html
drwxrwxr-x 2 user user 4096 Ağu 11 13:41 .
drwxrwxr-x 4 user user 4096 Ağu 11 13:48 ..
user#host:/tmp$ ls -alrt Directory_2/
total 20
-rw-rw-r-- 1 user user 7 Ağu 11 13:28 3.html
-rw-rw-r-- 1 user user 6 Ağu 11 13:28 2.html
-rw-rw-r-- 1 user user 6 Ağu 11 13:28 1.html
-rw-rw-r-- 1 user user 0 Ağu 11 13:44 5.html
drwxrwxr-x 2 user user 4096 Ağu 11 13:44 .
drwxrwxr-x 4 user user 4096 Ağu 11 13:48 ..
You can use comm command to compare sorted files. This might be the actual solution you are looking for.
Syntax: comm file1 file2
Compare sorted files FILE1 and FILE2 line-by-line.
With no options, comm produces three-column output. Column one contains lines unique to FILE1, column two contains lines unique to FILE2, and column three contains lines common to both files. Each of these columns can be suppressed individually with options.
Keep the comm command in a loop such that it compares all the files in your required directories.
If you want to compare files one by one manually:
You need to use diff command to display line-by-line difference between two files.
Syntax: diff path/FILE1 path/FILE2
You can use --changed-group-format and --unchanged-group-format options to filter required data.
Following three options can use to select the relevant group for each option:
'%<' get lines from FILE1
'%>' get lines from FILE2
'' (empty string) for removing lines from both files.
Example: diff --changed-group-format="%<" --unchanged-group-format="" file1 file2
You can get a clear-cut visual difference between two text files using the command sdiff:
Syntax: sdiff path/file1 path/file2
If you have vim editor installed
use: vim -d file1 file2

store a result of a command into a variable using csh

I'm trying to store a result of a command into a variable so I can display it nicely along with some text in one long not have it display the output and then newline then my text, in my csh script.
#! /bin/csh -f
if ("$1" == "-f" && $#argv == 1 ) then
grep 'su root' /var/adm/messages.[0-9] | cut -c 21-250
grep 'su root' /var/adm/messages
else if( $#argv > 0 ) then
echo "Usage : [-f]"
else
grep 'su root' /var/adm/messages.[0-9] /var/adm/messages | wc -l
printf "failed su attempts between Nov 02 and Oct 28\n"
endif
this command in the script
grep 'su root' /var/adm/messages.[0-9] /var/adm/messages | wc -l
gives me 21 when i run it, and i want 21 to be stored in a variable.
so i can just display the output of
21 failed su attempts between Nov 02 and Oct 28
and not
21
failed su attempts between Nov 02 and Oct 28
or if theres an easier way that doesn't involve variables open to that too.
You can use set and backticks (``). Something like
set count=`grep 'su root' /var/adm/messages.[0-9] /var/adm/messages | wc -l`
printf "$count failed su attempts between Nov 02 and Oct 28\n"
or
printf "%s failed su attempts between Nov 02 and Oct 28\n" "$count"
or without a variable, like
printf "%s failed su attempts between Nov 02 and Oct 28\n" \
`grep 'su root' /var/adm/messages.[0-9] /var/adm/messages | wc -l`

What does ^ character mean in grep ^d?

When I do ls -l | grep ^d it lists only directories in the current directory.
What I'd like to know is what does the character ^ in ^d mean?
The caret ^ and the dollar sign $ are meta-characters that respectively match the empty string at the beginning and end of a line.The grep is matching only lines that start with "d".
To complement the good answer by The New Idiot, I want to point out that this:
ls -l | grep ^d
Shows all directories in the current directory. That's because the ls -l adds a d in the beginning of the directories info.
The format of ls -l is like:
-rwxr-xr-x 1 user group 0 Jun 12 12:25 exec_file
-rw-rw-r-- 1 user group 0 Jun 12 12:25 normal_file
drwxr-xr-x 16 user group 4096 May 24 12:46 dir
^
|___ see the "d"
To make it more clear, you can ls -lF to include a / to the end of the directories info:
-rwxr-xr-x 1 user group 0 Jun 12 12:25 exec_file*
-rw-rw-r-- 1 user group 0 Jun 12 12:25 normal_file
drwxr-xr-x 16 user group 4096 May 24 12:46 dir/
So ls -lF | grep /$ will do the same as ls -l | grep ^d.
It has two meanings. One as 'The New Idiot' above pointed out. The other, equally useful, is within character class expression, where it means negation: grep -E '[^[:digit:]]' accepts any character except a digit. The^` must be the first character within [].

Resources