I'm new to shell and still practicing on it.
When I typed
ls /bin
The shell prints many files
'[' mousetweaks
aa-enabled mscompress
aa-exec msexpand
aa-features-abi mt
aconnect mt-gnu
..
But when I typed
ls -l /bin
I was expecting the same output file in long format, but it seems like the shell just gives me a soft link
lrwxrwxrwx 1 root root 7 Sept 5 15:22 /bin -> usr/bin
I can't figure out why.
The POSIX specification for ls says this:
-l(The letter ell.) Do not follow symbolic links named as operands unless the -H or -L options are specified. Write out in long format (see the STDOUT section). Disable the -C, -m, and -x options.
If you want to change the behavior, in addition to the two options specified above, you can also put a trailing slash after the name (i.e., /bin/ instead of /bin).
Related
I am having trouble finding out how to set a directory as an argument in bash.
The directory I am trying to have as an argument is /home/rrodriguez/Documents/one.
Anywhere I try to look for an answer I see examples like dir = $1 but I cant seem to find an explanation of what this means or how to set it up so that it references my specific file location. Could anyone show me how to set up my variable for my path directory?
Adding my code for a better understanding of what im trying to do:
#!bin/bash
$1 == 'home/rrodriguez/Documents/one/'
dir = $1
touch -c $dir/*
ls -la $dir
wc$dir/*
Consider:
#!bin/bash
dir=$1
touch -c "$dir"/*
ls -la "$dir"
This script takes one argument, a directory name, and touches files in that directory and then displays a directory listing. You can run it via:
bash script.sh 'home/rrodriguez/Documents/one/'
Since home/rrodriguez/Documents/one/ is the first argument to the script, it is assigned to $1 in the script.
Notes
In shell, never put spaces on either side of the = in an assignment.
I omitted the line wc$dir/* because it wasn't clear to me what the purpose of it was.
I put double-quotes around $dir to prevent the shell from, among other things, performing word-splitting. This would matter if dir contains spaces.
When I enter this command:
./vw -d click.train.vw -f click.model.vw --loss_function logistic
on cygwin I got this error:
-bash: ./vw: No such file or directory
I actually want to implement "PREDICTING CTR WITH ONLINE MACHINE LEARNING" website link for reference :
http://mlwave.com/predicting-click-through-rates-with-online-machine-learning/
Any help would be appreciated.
Answer based on common mistakes.
Execution by inexact name
Filename with blanks
Suppose you write ls in the command line and obtain the following:
$ ls
anyfile command
Then, you call your command with ./command and get the following:
$ ./command
bash: ./command: No such file or directory
Here you can think ls is wrong, but the actuality is that you can't easily recognize if a filename have, for example, leading or trailing spaces:
$ ls -Q # -Q, --quote-name -> enclose entry names in double quotes
"anyfile" "command "
As you see, here my command has a trailing space:
$ ./"command " # it works
Filename with extension
A common mistake is to call the command by the name without the extension (if any).
Let's name the command: command.sh:
$ ./command # wrong
$ ./command.sh # OK
Wrong file path
If you call your command with the prefix ./, it needs to be in your current directory ($PWD). If it is not, you will get:
$ ./command # relative path -> same as "$PWD/command"
bash: ./command: No such file or directory
In that case, you can try the following:
Executing the command by its absolute path
$ /home/user/command # absolute path (example). It starts with a slash (/).
Let the shell locate the command
If you provide just the command name without slashes, bash searches in each directory of the $PATH variable, for an executable file named command.
$ command
You can do that search with the which command:
$ which command
/usr/bin/command
If the search fails, you'll get comething like:
$ which unexistent_command
which: no unexistent_command in (/usr/local/sbin:/usr/local/bin:/usr/bin)
Broken link
Now, suppose you write ls -Q in the command line and obtain the following:
$ ls -Q
"anyfile" "command"
This time, you can be 100% secure command exists but when you try to execute it:
$ ./command
bash: ./command: No such file or directory
Reason? bash complains command doesn't exist, but what doesn't exist is the file command is pointing to by a Symbolic link. e.g.:
$ ls -l
total 0
-rw-r--r-- 1 user users 0 Jan 14 02:12 anyfile
lrwxrwxrwx 1 user users 27 Jan 14 02:12 command -> /usr/bin/unexistent_command
$ ls /usr/bin/unexistent_command
ls: cannot access /usr/bin/unexistent_command: No such file or directory
Notice that the following surely throw different errors that the one you are getting...
Execution permission
To execute a file, it must have the x bit activated. With ls -l you can check the file permission.
$ ls -l command
-rw-r--r-- 1 user users 0 Jan 3 19:52 command
In this case (it doesn't have the x bit activated), you can give permission with chmod:
$ chmod +x command
$ ls -l command
-rwxr-xr-x 1 user users 0 Jan 3 19:52 command
I'm reading this article, but I don't understand how I can combine ls -l /users/Thomas/desktop with ls > ~/FILE.txt to save the contents of the desktop to a file on the desktop (or somewhere else). Also, is there a way to save the type of element being listed (file or folder)?
Thanks!
Combining ls arguments with redirection:
ls -l /users/Thomas/desktop > ~/FILE.txt
-p option adds type indicator, showing trailing / for directories:
ls -lp /users/Thomas/desktop > ~/FILE.txt
~/FILE.txt is created in your home directory (echo "$HOME" is a good way to know where it is).
[Answering an extra question in the comment]: there is a number of short options (one-letter options) controlling sort order: -t, -S, -U and -X, having a common long-form equivalent --sort=time|size|none|extension. Additionally, --time=atime|access|use specifies the kind of time to be used for ls -t/ls --sort=time.
I am trying to use the output from mdfind to create a bunch of symlinks. Output of mdfind is like this:
/pathtofile1/
/pathtofile2/
/pathtofile3/
So, I used sed to add ln -s to the start of each line, and awk {print $0 "/directory where I want this/"};
after my single-line script successfully outputs this:
ln -s "/pathtofile1/" "/directory where I want this"
ln -s "/pathtofile2/" "/directory where I want this"
ln -s "/pathtofile3/" "/directory where I want this"
Problem is, when I run this, I get this error: "/directory where I want this: File does not exist"
The weird thing is that when I run these lines individually, they links are created as expected, but running the entire command returns the error above.
Any ideas?
I don't think that this is the ideal way to do what I'm trying to do, so let me know if you have any better solutions.
Edited with more information.
#! /bin/bash
itemList=`mdfind -s "$1"| awk '{ print "ln -s \""$0"\" \"/Users/username/Local/Recent\""}'`
echo "$itemList"
`$itemList`
$1 is a test *.savedSearch that returns a list of files.
My result (from the echo) is:
ln -s "/Users/username/Dropbox/Document.pdf" "/Users/username/Local/Recent"
ln -s "/Users/username/Dropbox/Document2.pdf" "/Users/username/Local/Recent"
and the error that I get is:
ln: "/Users/username/Local/Recent": No such file or directory
But, if I run a copy-pasted of each line individually, the links are created as expected.
One way to keep it simple:
mdfind -0 "query" | ( cd "/Users/username/Local/Recent" ; xargs -0 -I path ln -s path . )
This is of course doesn't handle duplicate file names, etc.
EDIT:
The reasons your solution is failing is that, first, the contents of $itemList is being executed as one long command (i.e. the line feeds output by awk are ignored), and then, second, the command substitution occurs before quote removal. What is actually processed is roughly equivalent to:
ln '-s' '"/pathtofile1/"' '"/to"' 'ln' '-s' '"/pathtofile2/"' '"/to"' 'ln' '-s' '"/pathtofile3/"' '"/to"'
/bin/ln recognizes this as the:
ln [-Ffhinsv] source_file ... target_dir
form of the command and checks to see that the final parameter is an existing directory. That test fails because the directory name includes the surrounding quote marks. Note carefully the error message you report and compare:
$ ln a b c "/Users/username/Local/Recent"
ln: /Users/username/Local/Recent: No such file or directory
$ ln a b c '"/Users/username/Local/Recent"'
ln: "/Users/username/Local/Recent": No such file or directory
So the morals of the story are, when you are dealing with file names in a shell, the safest solution is to avoid shell processing of the file names so you don't have to deal with quoting and other side effects (which is a big advantage of an xargs solution) and keep it simple: avoid constructing complex multi-line shell commands. It's too easy to get unexpected results.
It would be much easier to determine what the problem was if you used some actual, or at least plausible, paths as examples, but ln isn't going to create these directories for you if that's what you want.
I am trying to check if a symbolic link exists from a KornShell (ksh) script using -h filename command. This works good on HP boxes.
Not sure what is the correct option for Linux, AIX and Solaris boxes.
Any insight regarding this?
-h is part of the POSIX spec; it should work everywhere that is vaguely reasonable.
According to man test on Mac OS X:
-h file True if file exists and is a symbolic link. This operator
is retained for compatibility with previous versions of
this program. Do not rely on its existence; use -L instead.
-L is also standardized, so if you find anywhere that -h does not work, you should try -L instead.
It is -h on linux systems also, at least (bash is my shell):
lrwxrwxrwx 1 mule mule 37 Feb 27 09:43 mule.log -> /home/mule/runtime/mule/logs/mule.log
[mule#emdlcis01 ~]$ if [[ -h mule.log ]]; then echo "mule.log is a symlink that exists" ; fi
mule.log is a symlink that exists
Check man test to see the available operators you have available to use on files and strings in your given enviorment.
The best answer is to try whatever the 'test' man page says on your system. If that seems to work, look no further. However, if it doesn't seem to work, or if you have questions about more obscure options to test, then you should also check the man page for your shell to see if 'expr' or '[' are built-ins. In that case, the shell might be using an internal implementation instead of calling the expr utility from /bin. On Solaris I verified that ksh93 treats [ as a builtin (even though the man page doesn't seem to say so). From the truss output you can see that ksh is not running the expr command for [.
% truss -f -texec /bin/ksh '[ -h /home ]'
26056: execve("/usr/bin/ksh", 0x08047708, 0x08047714) argc = 2
26056: execve("/usr/bin/ksh93", 0x08047708, 0x08047714) argc = 2
26056: execve("/usr/bin/amd64/ksh93", 0x08047704, 0x08047710) argc = 2
% truss -f -texec /bin/ksh '/bin/expr -h /home ]'
26058: execve("/usr/bin/ksh", 0x08047700, 0x0804770C) argc = 2
26058: execve("/usr/bin/ksh93", 0x08047700, 0x0804770C) argc = 2
26058: execve("/usr/bin/amd64/ksh93", 0x080476FC, 0x08047708) argc = 2
26058: execve("/bin/expr", 0x00418360, 0x00418398) argc = 4
Thw two possible options are
if [ -h filename ]
OR
ls -ltr | grep filename | grep ^l
If $? is 0 then file is linked otherwise its not linked, I will prefer the first option instead.