LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 08-12-2011, 07:11 AM   #1
UNGR
LQ Newbie
 
Registered: Aug 2011
Location: Denmark
Distribution: Ubuntu
Posts: 8

Rep: Reputation: Disabled
Need a non-binary alternative to the "test" command


Hi everyone!

I am currently in the very very early stages of learning how to use the bash shell as well as how to make scripts for it.

Now I have a folder with pictures in it.. They are named chronologically in the following order: YYYYMMDD, for example 20090101 is January 1st, 2009. I am writing a small script which I want to do the following:

1. Check if there are any files from January
2. If there are, make a new directory called "January" and move them in there.

Now this is a very simple script, and this is what I got for now:
Code:
#! /bin/bash

PIC_DIR=/path/to/my/pictures


if [ -e $PIC_DIR/200901* ] ; then 
	mkdir $PIC_DIR/January
	mv $PIC_DIR/200901* $PIC_DIR/January
fi
This script works perfectly, as long as I only have one file that fits the criteria of having a filename of 200901*.

There is a problem with this script, though: The "test" command (the []) can only evaluate true/false statements and then exit with a 0 or a 1, accordingly. If I have several files from January 2009, it does not know which one to look at, and it exits with the error:
Code:
/path/to/the/script/script.bash: line 6: [: path/to/my/pictures/20090101: binary operator expected
So I am looking for a command that will test whether there are ANY files with the name of 200901* - not if there is a single file with the name of 200901*. Any suggestions?

Best regards,
~UNGR

P.S. I realize my writing may be a little confusing, since I am still learning this and don't fully understand it all. If you need any clarifications, please don't hesitate to ask. I welcome all help!

P.P.S. I have used these forums quite a bit, but this is my very first question. You all seem like a bunch of great guys, and I'm looking forward to ruthlessly leech on your knowledge!

Last edited by UNGR; 08-12-2011 at 07:13 AM.
 
Old 08-12-2011, 07:48 AM   #2
janhe
Member
 
Registered: Jul 2007
Location: Belgium
Distribution: slackware64 13.1, slackware 13.1
Posts: 369

Rep: Reputation: 49
It seems you've read up quite a few things about the if test in bash. So I'm going to give you a slightly advanced answer.
So if only looks at the exit status of the test program ([ is simply an alias for test, as you probably knew already).

As you probably already know, other programs also have exit statuses. if can use these the same way it uses the exit status of test.

The real problem you are facing, is that test now gets fed a commandline like this:
Code:
test -e path/to/my/pictures/20090101 path/to/my/pictures/20090102 path/to/my/pictures/20090103 path/to/my/pictures/20090114
It only expects one filename after the -e argument, so the other filenames are confusing test. It sees more than one filename, so it says it wants an operator that can handle 2 arguments (-e is an operator that can handle 1 argument).
An operator that can handle 2 arguments is a binary operator, binary refers to "has 2 sides", not "is made up of 1s an 0s".

Now the problem is understood, the solution.
ls is a command that can accept multiple filenames. If it cannot find any files, it exits with exit status 2, if it can it exits with exit status 0. So if can be used together with ls to find out if there is any number of files with that name-pattern.

so this should work:
Code:
if ls path/to/my/pictures/200901*
then
  do_something
fi
This outputs error messages and a list of your files, if applicable. You probably don't want that in your script.
Also, this is quite unreadable for people who aren't used to using if this way.
Using $?, the variable with the last command's exit status, is more common.
This suppresses the output of ls and uses $?:
Code:
ls dinge > /dev/null 2>&1
if [ $? -eq 0 ]
then
  do_something
fi
PS: -eq is a binary operator, it looks at the things on its left and on its right
 
1 members found this post helpful.
Old 08-12-2011, 08:00 AM   #3
UNGR
LQ Newbie
 
Registered: Aug 2011
Location: Denmark
Distribution: Ubuntu
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thank you VERY much for your answer - very quick and very detailed!

Now I understood why it would suppress the output of ls to send it to the /dev/null, but what is the "dinge" in line 1 of your solution (seen below)? This is probably incredibly basic, but the guide/tutorial I followed did not cover this.

Quote:
Originally Posted by janhe View Post
Code:
ls dinge > /dev/null 2>&1
if [ $? -eq 0 ]
then
  do_something
fi
Thanks for your time! It is much appreciated!

Last edited by UNGR; 08-12-2011 at 08:06 AM.
 
Old 08-12-2011, 08:03 AM   #4
janhe
Member
 
Registered: Jul 2007
Location: Belgium
Distribution: slackware64 13.1, slackware 13.1
Posts: 369

Rep: Reputation: 49
oops...
"dinge" is a Dutch dialect word for "stuff"

I use it a lot for temporary files and testing commands.
You should substitute it for your file name pattern, like:
Code:
ls path/to/my/pictures/200901* > /dev/null 2>&1
 
1 members found this post helpful.
Old 08-12-2011, 08:07 AM   #5
UNGR
LQ Newbie
 
Registered: Aug 2011
Location: Denmark
Distribution: Ubuntu
Posts: 8

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by janhe View Post
oops...
"dinge" is a Dutch dialect word for "stuff"

I use it a lot for temporary files and testing commands.
You should substitute it for your file name pattern, like:
Code:
ls path/to/my/pictures/200901* > /dev/null 2>&1
Ah - that's what I figured Could find it anywhere in the man pages either

Also, I have a single last question: The "2>&1" - what exactly does this do? My guide used ">&2" and said it was something about redirecting to Standard Error... Would you care to elaborate on this? And bear in mind, I started learning this about four days ago, so please go real slow on me!

Thanks again for your time - it is VERY much appreciated!

Last edited by UNGR; 08-12-2011 at 08:09 AM.
 
Old 08-12-2011, 08:30 AM   #6
janhe
Member
 
Registered: Jul 2007
Location: Belgium
Distribution: slackware64 13.1, slackware 13.1
Posts: 369

Rep: Reputation: 49
2>&1 redirects the output that the program sends to Standard Error to Standard Output
>&2 redirects the output that the program sends to Standard Output to Standard Error

Standard Output, Input and Error explanation: http://en.wikipedia.org/wiki/Standard_streams
redirection explanation: http://en.wikipedia.org/wiki/Redirection_(computing)
guide with an even better explanation of these (and more): http://tldp.org/HOWTO/pdf/Bash-Prog-Intro-HOWTO.pdf

Most programs send their output to stdout. If an error occurs, like "file not found" they send an error message to stderr. If you are simply typing in a command on the terminal, both stdout and stderr outputs are simply shown on the screen.

If you want to save the output of a command to a file, you can do that with a command like "ls -l > file"
But you probably don't want ugly error messages mixed with your pretty program output. That's why output and error are on a separate "channel".
But sometimes you do want this. That's why the 2>&1 and the other exist. I simply put both in /dev/null. Your guide preserved both on stderr, as a sort of debugging output.

PS: If you didn't already, check out some of the howtos on The Linux Documentation Project (where the Bash Programming Howto came form).

PPS: there seems to be a convention to welcome people to LQ when responding to their first post. I always forget to do that:
Hi, welcome to LinuxQuestions.org! Enjoy your stay on these forums.
 
1 members found this post helpful.
Old 08-12-2011, 05:43 PM   #7
qlue
Member
 
Registered: Aug 2009
Location: Umzinto, South Africa
Distribution: Crunchbangified Debian 8 (Jessie)
Posts: 747
Blog Entries: 1

Rep: Reputation: 172Reputation: 172
Quote:
Originally Posted by janhe View Post
oops...
"dinge" is a Dutch dialect word for "stuff"

I use it a lot for temporary files and testing commands.
You should substitute it for your file name pattern, like:
Code:
ls path/to/my/pictures/200901* > /dev/null 2>&1
And here I thought it was Afrikaans! :P :lol:
 
Old 08-12-2011, 06:42 PM   #8
janhe
Member
 
Registered: Jul 2007
Location: Belgium
Distribution: slackware64 13.1, slackware 13.1
Posts: 369

Rep: Reputation: 49
Quote:
Originally Posted by qlue View Post
And here I thought it was Afrikaans! :P :lol:
Who knows, maybe it is!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] Silencing the line "echo test > test/test.txt" in a shell script Arenlor Linux - General 2 06-18-2010 01:37 PM
[SOLVED] The special expression `-l STRING' for "test" command Star_Gazer Programming 4 04-22-2010 01:40 AM
alternative command for "find -mtime " sspisharody Linux - Newbie 2 02-13-2009 04:41 PM
Is there an alternative command for "ipmasqadm" on Fedora Core 6? bluntvillan Linux - Networking 1 02-24-2008 12:14 AM
Standard commands give "-bash: open: command not found" even in "su -" and "su root" mibo12 Linux - General 4 11-11-2007 10:18 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 11:13 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration