Bash脚本查找可执行文件的路径

时间:2021-03-06 22:08:36

EDIT: I KNOW THIS IS REDUNDANT, IT IS HOMEWORK, I HAVE WRITTEN MY OWN CODE AND NEED HELP TROUBLESHOOTING>

编辑:我知道这是多余的,这是家庭作业,我已经编写了我自己的代码,需要帮助诊断>

As stated, I must write a BASH script to determine whether an executable file is in the users path.

如前所述,我必须编写一个BASH脚本,以确定可执行文件是否在用户路径中。

such that if you type
./findcmd ping it returns /bin/ping

这样,如果您输入。/findcmd ping,它将返回/bin/ping

I have some code written, But it does not properly work and I hope someone can help me troubleshoot. When I type ./findcmd ping it just returns my file does not exist.(with any other file I try as well that I know exists.)

我已经编写了一些代码,但是它不能正常工作,我希望有人能帮助我排除故障。当我输入。/findcmd ping时,它会返回我的文件不存在。(还有其他文件,我也知道是存在的。)

#!/bin/bash
#
# Invoke as ./findcmd command
#
# Check for argument
if [[ $# -ne 1 ]]
 then
    echo 'useage: ./findcmd command'
    exit 1
fi
#
# Check for one argument
if [[ $# -eq 1 ]]
 then
     pathlist=`echo $PATH | tr ':' ' '`
     for d in $pathlist;
          do
             if [[ ! -d $d || ! -x $d || ! -r $d ]]
               then
                   echo 'You do not have read end execute
                          permissions!'
                   exit 2
              fi
              if [[ $(find $d -name $1 -print | wc -l) -ne 0 ]]
                   then
                         echo 'The file does not exist in the PATH!'
                          exit 0

             fi
        done
fi

exit 0
#
#

2 个解决方案

#1


3  

No need to use a bash array, tr'ing the ':' with ' ' will work just fine in a for loop.

不需要使用bash数组,tr':' with '将在for循环中正常工作。

#!/bin/bash
#
# Invoke as ./findcmd command
#
# Check for argument
if [[ $# -ne 1 ]]
 then
    echo 'usage: ./findcmd command'
    exit 1
fi

f=$1

# No need to check the $# again, there's at least one arg and other will be ignored..
# Otherwise you can wrap this in a loop and keep shift'ing args and checking one by one
pathlist=`echo $PATH | tr ':' '\n'`
for d in $pathlist;
    do
      #echo command is your friend
      #echo "Checking for $f in $d"
      path="$d/$f"
      if [[ -f "$path" && -x "$path" ]]; then
         # PATH is not recursive, therefore no need to use find command
         # Simply checking that the file exists and is executable should be enough
         echo "Found $f at '$path'"
         # Note the same filename may be present farther down the PATH 
         # Once the first executable is found, exit
         exit 0
      fi
done

# Getting here means file was not found
echo "$f could not be found"
exit 1

Here are the results:

这里是结果:

rbanikaz@lightsaber:~$ ./which.sh grep
Found grep at '/usr/bin/grep'
rbanikaz@lightsaber:~$ ./which.sh foo
foo could not be found
rbanikaz@lightsaber:~$

#2


-1  

The which command already does this...

哪个命令已经这样做了……

Techinically this is a solution...

这是一个解决方案……

#!/bin/bash
which $1

I probably wouldn't submit it for as assignment though...

我可能不会把它作为作业提交…

Update

Messing around a bit and I think the following will code will get your past your current bug:

我认为下面的代码可以帮你解决当前的问题:

#!/bin/bash
#
# Invoke as ./findcmd command
#
# Check for argument
if [[ $# -ne 1 ]]
 then
    echo 'useage: ./findcmd command'
    exit 1
fi
#
# Check for one argument
if [[ $# -eq 1 ]]
 then
     d=$1
     pathlist=($(echo $PATH | tr ':' ' '))
     echo $pathlist

     i=0
    while read line; do
      a4[i++]=$line
    done < <(echo "$PATH" | tr ':' '\n')

    n=${#a4[@]}
    for ((i=0; i < n; i++)); do
       if [[ ! -d $d || ! -x $d || ! -r $d ]]
       then
          echo 'You do not have read end execute
                          permissions!'
          exit 2
       fi
       if [[ $(find $d -name $1 -print | wc -l) -ne 0 ]]
       then
          echo 'The file does not exist in the PATH!'
          exit 0

       fi
    done
fi

exit 0
#
#

Pretty much, it uses a solution in this SO question to split the $PATH variable into an array and then loops through it, applying the logic you had inside your while statement.

基本上,它在这个问题中使用一个解决方案将$PATH变量分割成一个数组,然后循环遍历它,应用你在while语句中所包含的逻辑。

#1


3  

No need to use a bash array, tr'ing the ':' with ' ' will work just fine in a for loop.

不需要使用bash数组,tr':' with '将在for循环中正常工作。

#!/bin/bash
#
# Invoke as ./findcmd command
#
# Check for argument
if [[ $# -ne 1 ]]
 then
    echo 'usage: ./findcmd command'
    exit 1
fi

f=$1

# No need to check the $# again, there's at least one arg and other will be ignored..
# Otherwise you can wrap this in a loop and keep shift'ing args and checking one by one
pathlist=`echo $PATH | tr ':' '\n'`
for d in $pathlist;
    do
      #echo command is your friend
      #echo "Checking for $f in $d"
      path="$d/$f"
      if [[ -f "$path" && -x "$path" ]]; then
         # PATH is not recursive, therefore no need to use find command
         # Simply checking that the file exists and is executable should be enough
         echo "Found $f at '$path'"
         # Note the same filename may be present farther down the PATH 
         # Once the first executable is found, exit
         exit 0
      fi
done

# Getting here means file was not found
echo "$f could not be found"
exit 1

Here are the results:

这里是结果:

rbanikaz@lightsaber:~$ ./which.sh grep
Found grep at '/usr/bin/grep'
rbanikaz@lightsaber:~$ ./which.sh foo
foo could not be found
rbanikaz@lightsaber:~$

#2


-1  

The which command already does this...

哪个命令已经这样做了……

Techinically this is a solution...

这是一个解决方案……

#!/bin/bash
which $1

I probably wouldn't submit it for as assignment though...

我可能不会把它作为作业提交…

Update

Messing around a bit and I think the following will code will get your past your current bug:

我认为下面的代码可以帮你解决当前的问题:

#!/bin/bash
#
# Invoke as ./findcmd command
#
# Check for argument
if [[ $# -ne 1 ]]
 then
    echo 'useage: ./findcmd command'
    exit 1
fi
#
# Check for one argument
if [[ $# -eq 1 ]]
 then
     d=$1
     pathlist=($(echo $PATH | tr ':' ' '))
     echo $pathlist

     i=0
    while read line; do
      a4[i++]=$line
    done < <(echo "$PATH" | tr ':' '\n')

    n=${#a4[@]}
    for ((i=0; i < n; i++)); do
       if [[ ! -d $d || ! -x $d || ! -r $d ]]
       then
          echo 'You do not have read end execute
                          permissions!'
          exit 2
       fi
       if [[ $(find $d -name $1 -print | wc -l) -ne 0 ]]
       then
          echo 'The file does not exist in the PATH!'
          exit 0

       fi
    done
fi

exit 0
#
#

Pretty much, it uses a solution in this SO question to split the $PATH variable into an array and then loops through it, applying the logic you had inside your while statement.

基本上,它在这个问题中使用一个解决方案将$PATH变量分割成一个数组,然后循环遍历它,应用你在while语句中所包含的逻辑。