1
#!/bin/bash
#
echo $PWD
cd /home/<my username>/<long path>
echo $PWD

What I get when executing it with bash script.sh:

/home/<my username>
: No such file or directorye/<my username>/<long path>
/home/<my username>

Or with bash . script.sh

.: .: is a directory

It looks like in first case it has just skipped first 4 characters (/hom) of the address line for no reason. And in second case, what the hell is .: .:? It's absolutely "ungooglable".

And ofc when I copypaste this line cd /home/<my username>/<long path> in terminal it works like it should.

EDIT: IT WAS ALL ABOUT ONE MISSING SPACE SYMBOL AT THE END OF THE PATH, THANK YOU.

  • When you run the script, a new instance/subshell will be created.

    Try sourcing the script using .[space]script.sh

    – Zwans Dec 28 '16 at 16:08
  • Also: http://unix.stackexchange.com/q/175611/117549 – Jeff Schaller Dec 28 '16 at 16:10
  • Maybe best duplicate: http://unix.stackexchange.com/a/27140/117549 – Jeff Schaller Dec 28 '16 at 16:11
  • @JeffSchaller I think the point of this is the "/home/" -> "e/" transformation rather than the "cd in a script doesn't work". – icarus Dec 28 '16 at 16:15
  • ... most likely a carriage return character got in the path string somehow. Please run cat -net script.sh and include the output in your question. – steeldriver Dec 28 '16 at 16:17
  • 1
    "." is the current directory. When you say bash . script.sh you are asking bash to execute the current directory passing script.sh as $1. At the risk of confusing things more, probably what was being asked of you was . script.sh (without bash) or just possible bash -c ". script.sh". – icarus Dec 28 '16 at 16:19
  • 1
    We can't really help unless you show us the exact path and the actual script. I am willing to bet you have an \r character somewhere in there (did you maybe edit this from Windows?) and that's why it's eating the first few characters but I can't be sure unless you upload the script somewhere and link it here. – terdon Dec 28 '16 at 17:00
  • You should edit the last part saying that the problem is not really a missing space, but the presence of "invisible" Newline (^M) characters in the script (created on windows). Those special characters are taken as part of the path itself, so adding a space separates them from the path, but the real fix is to get rid of those "^M" characters altogether, as they can have many similar unintended consequences. – Olivier Dulac Dec 28 '16 at 17:55

3 Answers3

3

You should

  • check the script for any "hidden characters" before your "/home" part (that would explain it can't cd to it, and why the display truncates part of it too). For example: cat -ve THEFILE # -e will mark each end of line with a $ and -v will show some of the control characters in the form ^x, ex: ^M for the control character "Carriage Return".

  • Fix it: For this, type a working example in your shell, then copy it using the mouse, and edit the script, delete the line, and paste the one you copied in its place. (in vi: if the script is exactly as described (and the faulty line is line 4) : you go to line 4 with 4G, then delete that line with dd, and go in Insert mode on the line above with: O (capital o). Then you can paste the lines you copied with the mouse. then Escape to go back to command mode, and :wq to write the changes it the file and quit vi.

  • You may want to compare the output $(pwd) with the value $PWD: try to replace the : echo $PWD with : pwd ; echo "PWD=$PWD"

  • finally : bash . script.sh should be: bash ./script.sh . The one you typed ask bash to execute "." with the argument "script.sh", and "." being a directory, bash complains. When invoked in this way, the complaint is usually on the form: program_name: some message . Here bash tries to execute the program ., so its error message mistakenly use .: as the program name prompt, and the message it displays is .: is a directory, indicating that it couldn't execute it and why (it is a directory, not a bash script).

  • Note that when you invode script.sh in this way (bash ./script.sh), you ask your current shell to invoke a bashsubshell that will execute script.shand exit. Only that bash subshell will be: echoing PWD, then cd-ing to the directory, the echoing the new PWD. When that bash exits, your current shell is still in the original directory. If you want to have a file making changes in your current shell, source it instead: . ./script.sh or in bash you also can source ./script.sh (note: . is the more portable way to source a file) (note 2: having a path for the file to source is recommended in recent shell, ie: . script.sh may work too, but it is recommended to specify the local path such as: . ./script.sh)

  • There are only these ^M$ hidden characters and I assume it's a simple end of line. No hidden characters between "cd" and "/home/...." – Sigmund Freud Dec 28 '16 at 17:12
  • @SigmundFreud : if there is one just at the end of , it is included in it and therefore that path becomes invalid. Add a space in between. or use: dos2unix <./script.sh >./script.sh_for_unix && mv ./script.sh_for_unix ./script.sh # to get rid of all those ^M, used in windows environment and causing those issues in an unix script. the < and > are needed in that command, and you shouldn't use it as a delimiter as you did in your question, as they are usually redirection commands (as in this command) – Olivier Dulac Dec 28 '16 at 17:16
  • 1
    OMG, I am in deep shock. Now it seems to work, thanks. – Sigmund Freud Dec 28 '16 at 17:18
  • @SigmundFreud: Glad it helped. you will have many similar missteps, but hang in there, unix scripting and its environment is worth it ! Read the wooledge.com site's "bashFAQ" "bash pitfalls" and "bash guide" pages, and you'll spare yourself a LOT of similar mistakes ^^ – Olivier Dulac Dec 28 '16 at 17:20
  • then I will ask next question right here instead of creating a new topic: – Sigmund Freud Dec 28 '16 at 17:20
  • So, my long directory ends with 0. Now I want to change this 0 for 1-9 in a loop and display it, what's wrong: for i in {1..9} do cd ../$i echo $PWD done P.S.: tired with this "Enter = send" – Sigmund Freud Dec 28 '16 at 17:22
  • @SigmundFreud: for i in /path/to/long/director{1..9} ; do cd "${i}" ; pwd ; done #note I remove the last char ("0") in the long directory name, so that instead you have the shell put "1", "2", ... "9" as needed. There are many other ways to do it – Olivier Dulac Dec 28 '16 at 17:24
  • @SigmundFreud: You seem to start in scripting, you should really read http://mywiki.wooledge.org/BashGuide , and quite quick (a bit later on) : http://mywiki.wooledge.org/BashPitfalls (a mine of good advices and not-so-well-known pitfalls that are easy to fall into) – Olivier Dulac Dec 28 '16 at 17:27
  • syntax error near unexpected token `cd'

    Thanks, I am not going to use this stuff very often. It is not simplifying my work, it only makes it harder. In most cases it will be easier to manually use the terminal than spending 5-10 hours to find this missing space symbol in script.

    – Sigmund Freud Dec 28 '16 at 17:29
  • @SigmundFreud: unexpected token? did you forget the "; do" ? – Olivier Dulac Dec 28 '16 at 17:30
  • OMG, it's not like any normal language, "do" must be in the same line with "cd", now it tells me "No such file or directory" 10 times in a row. – Sigmund Freud Dec 28 '16 at 17:32
  • @SigmundFreud: do is just needed to separate the list from the actions. usually for var in A LIST HERE ; do , then on the next line(s) the actions, then last line "done". a ";" act as a newline in this context. for the cd errors: Check you specified correctly the /path/to/long/director{1..9} part, it may be wrong. You can change to get more info : for i in /path/to/long/director{1..9} ; do echo "Trying to cd into : '$i' " ; cd "$i" ; pwd ; done – Olivier Dulac Dec 28 '16 at 17:35
  • now when I added one space at the end of /{0..9} and at the end of cd "${i}" it seems to work, almost like it should. I have 10 correct echos, but there is still an error at the end where it says me that longpath/9 doesnt exists despite correctly displaying it in the previous line. – Sigmund Freud Dec 28 '16 at 17:38
  • run the dos2unix command I provided : dos2unix <./script.sh >./corrected_script.sh && mv ./corrected_script.sh ./script.sh to get rid of the remaining "^M" . the echo just displays (so it always works): if the cd doesn't work maybe that exact directory doesn't exist? or you created it with an "^M" in its name? try: ls -l /path/to/long/ | cat -ve and check the names for invisible weird characters – Olivier Dulac Dec 28 '16 at 17:40
  • thank you, I will save it for future use. I am kinda disappointed in Notepad++ now. – Sigmund Freud Dec 28 '16 at 17:44
  • http://chat.stackexchange.com/rooms/info/50849/one-simple-little-cd-doesnt-work-in-script?tab=general if you have more questions. And keep using Notepad++, but by default, being in windows, it creates files FOR windows. open your script, and in bottom left corner click "Dos\windows" and convert it to "Unix (LF)" and save. Now it will keep it in the unix format – Olivier Dulac Dec 28 '16 at 17:47
  • 1
    thanks, where can I + your rep now? Can't find it anywhere. – Sigmund Freud Dec 28 '16 at 17:49
  • you can check the checkmark if you accept my answer. But usually it's best to wait 1 or 2 days, in case one of the wunderpersons in here step in and provide a much better answer (this happens! ^^ a lot, actually. Best to wait at least 48 hours before deciding who provided the best answer, ie the answer that covers everything (the more "portable" to other similar problems, the better). And welcome to the site! – Olivier Dulac Dec 28 '16 at 17:53
1

Your second question is easy:

.: .: is a directory

When you are running a Bash script and Bash encounters an error, it prints the name of the script and the line where the error was found, like so:

script.sh: line X: some message

The command line bash . something.sh attempts to run . as a script, and it thus fail. Maybe were you looking for bash ./script.sh? In that case, you don't need to specify the full path. Bash can find the script if you only do bash script.sh.

The output of your script is kind of strange:

: No such file or directorye/<my username>/<long path>

It is missing both the file information and part of the error message.

I'm guessing your script has some unintended unprintable characters. If this was written with an editor that uses CR-LF line terminators, you can import it with fromdos -b script.sh. The -b flag ensures that fromdos will leave a backup of your original file. If you are on Debian, you can install this program with the package tofrodos.

To verify whether you have unintended unprintable characters, use cat -A. Several interesting things may show up. For instance, TABs will print as ^I and newlines as $. If your file does have MS-DOS style line feeds, they will appear as ^M$.

giusti
  • 1,737
  • 2
  • 16
  • 31
0

Can you do following command and run it again ?

dos2unix script.sh

If still not working , remove non-printable letters from file using below command

tr -cd "[:print:]" script.sh > script2.sh bash script2.sh

Rajeev
  • 261