114

I'm writing a script in Unix where I have to check whether the first character in a string is "/" and if it is, branch.

For example, I have a string:

/some/directory/file

I want this to return 1, and:

[email protected]:/some/directory/file

to return 0.

1

5 Answers 5

198

There are many ways to do this. You could use wildcards in double brackets:

str="/some/directory/file"
if [[ $str == /* ]]; then echo 1; else echo 0; fi

You can use substring expansion:

if [[ ${str:0:1} == "/" ]] ; then echo 1; else echo 0; fi

Or a regex:

if [[ $str =~ ^/ ]]; then echo 1; else echo 0; fi
Sign up to request clarification or add additional context in comments.

1 Comment

To short, use: ${str::1}.
20

Consider the case statement as well which is compatible with most sh-based shells:

case $str in
/*)
    echo 1
    ;;
*)
    echo 0
    ;;
esac

4 Comments

I thought glob * only matches a single path component, never across slashes /
The relevant POSIX quote is: pubs.opengroup.org/onlinepubs/9699919799/utilities/… "Case Conditional Construct" sentence "corresponding to the first one of several patterns (see Pattern Matching Notation)"
Also if you want to match a # you'll have to use quotes. For example: '#'*) echo "found comment";;.
I happen to have to write POSIX-compliant code (/bin/sh) thus @konsolebox's answer (although quite old) was most useful, thanks @konsolebox!
13
$ foo="/some/directory/file"
$ [ ${foo:0:1} == "/" ] && echo 1 || echo 0
1
$ foo="[email protected]:/some/directory/file"
$ [ ${foo:0:1} == "/" ] && echo 1 || echo 0
0

4 Comments

Downvote! You forgot to quote your variable in single braces. foo='*'; [ ${foo:0:1} == "/" ] && echo 1 || echo 0 is going to output this error bash: [: too many arguments. Use [ "${foo:0:1}" == "/" ] && echo 1 || echo 0 or even better [[ ${foo:0:1} == "/" ]] && echo 1 || echo 0
@Aleks-DanielJakimenko-A. - devnull's answer works without error in "GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu) Copyright (C) 2013 Free Software Foundation, Inc."
Your initial expression: "Downvote! You forgot to quote your variable in single braces." implies that the expressions entered in devnulls answer won't work as is on bash. You need to modify that initial expression in order to properly deliver your technical point, otherwise it isn't logically correct.
@Mausy5043 it's not a “typo”, it is buggy and incorrect.
10

printf '%c' "$s"

This was mentioned by brunoais in a comment, and it might be the best option since:

  • it is likely POSIX. TODO confirm. The following quote from https://pubs.opengroup.org/onlinepubs/9699919799/utilities/printf.html suggests this:

    It shall not be considered an error if an argument operand is not completely used for a b, c, or s conversion.

  • it can extract the character to a variable unlike using case directly

  • unlike cut -c1 printf is a Bash built-in so it could be a little bit faster

myvar=abc
first_char="$(printf '%c' "$myvar")"
if [ "$first_char" = a ]; then
  echo 'starts with a'
else
  echo 'does not start with a'
fi

cut -c1

This is POSIX, and unlike case:

myvar=abc
first_char="$(printf '%s' "$myvar" | cut -c1)"
if [ "$first_char" = a ]; then
  echo 'starts with a'
else
  echo 'does not start with a'
fi

awk substr is another POSIX command, but less efficient alternative:

printf '%s' "$myvar" | awk '{print substr ($0, 0, 1)}'

printf '%s' is to avoid problems with escape characters: Bash printf literal verbatim string, e.g.,

myvar='\n'
printf '%s' "$myvar" | cut -c1

outputs \ as expected.

${::} does not seem to be POSIX.

See also: How can I extract the first two characters of a string in shell scripting?

4 Comments

Why the printf? Would that be because echo would remove spaces?
@AlexisWilke echo has implementation defined behaviour on escapes I think: stackoverflow.com/questions/8467424/…
Specifically in the case of first char, you can use first_char="$(printf '%c' "$myvar")"
@brunoais et al – I've never understood why POSIX printf does that; isn't %c supposed to take an integer and represent its character code? I expect printf "%c" 65 to have the same output as awk 'BEGIN { printf "%c", 65 }' (which produces A), yet I instead get 6.
3

Code:

 place="Place"
 fchar=${place:0:1}
 echo $fchar

Output:

P

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.