3

experts

I want to create file in each folder . Here is my command

for i in `ls`;do cd $i;touch test.txt;done

-bash: cd: 10/: No such file or directory
-bash: cd: 2/: No such file or directory
-bash: cd: 3/: No such file or directory
-bash: cd: 4/: No such file or directory
-bash: cd: 5/: No such file or directory
-bash: cd: 6/: No such file or directory
-bash: cd: 7/: No such file or directory
-bash: cd: 8/: No such file or directory
-bash: cd: 9/: No such file or directory

It only generate test.txt in folder 1/, the rest folder are blank. I think the reason is my command lack of { } to clarify the scale of LOOP for .

could you please help me update my command?

2
  • sorry , I should use ( ) instead of { } to achieve it . Commented May 11, 2018 at 7:05
  • it should be like for i in */;do (cd $i;ls;cd -);done Commented May 11, 2018 at 7:05

4 Answers 4

4
for dir in */; do
   touch "$dir/test.txt"
done
  1. There's no need to cd into a directory to create a file there.
  2. Don't parse the output of ls. The output of ls is only for looking at. Parsing it will break if your files or directories have names containing literal newlines or spaces.
  3. The pattern */ will match any directory in the current directory.
  4. Quote your variable expansions. Your code would break if IFS is set to a digit.

If you really need to do a cd into the directory, do it in a subshell. The changed working directory only affects the subshell and there is no need to cd back.

for dir in */; do
   ( cd "$dir" && touch test.txt )
done
Sign up to request clarification or add additional context in comments.

1 Comment

yes, it is truly right. my original purpose is update the command like ` for i in */;do (cd $i;ls;cd -);done`, but your command is more efficency.
1

Let's consider that you have the following 10 folders in your current working directory:

tree .
.
├── 1
├── 10
├── 2
├── 3
├── 4
├── 5
├── 6
├── 7
├── 8
└── 9

you can run the following command, to create your files:

for d in `find . -mindepth 1 -maxdepth 1 -type d`; do touch "$d"/test.txt; done

OUTPUT:

tree .
.
├── 1
│   └── test.txt
├── 10
│   └── test.txt
├── 2
│   └── test.txt
├── 3
│   └── test.txt
├── 4
│   └── test.txt
├── 5
│   └── test.txt
├── 6
│   └── test.txt
├── 7
│   └── test.txt
├── 8
│   └── test.txt
└── 9
    └── test.txt

10 directories, 10 files

Explanations:

find . -mindepth 1 -maxdepth 1 -type d will get all the folders that are exactly 1 level under your current working folder if you omit -mindepth 1 then you will have a file created in your current working directory since . will be selected, if you omit -maxdepth 1 then file will be created recursively at any depth level, also -type d will allow to filter only on directories.

You can then use a loop to create the files or even xargs command would be enough

1 Comment

thanks, you inspired me , that I should type for i in ls;do touch $i/test.txt;done . but your method is more accurate to make sure right result.
1

You cd into a directory, but you don't cdback out. Assuming that the first directory in the list is 1, your script first changes into 1, and next tries to change into 1/10, which does not exist.

You could do a cd - after touching the file.

Even better, you avoid the cd altogether and do a touch $i/test.txt instead.

Of course, the script as written is not very robust: It breaks, if the current directory contains plain files, and it breaks if it contains entries which have spaces in their names - but this is a different issue.

Comments

0

Changing your command a bit,

for i in `ls -1`;do touch "$i"/test.txt;done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.