First of all, this is the code;
#!/bin/bash
i=1;
while read line;
do
cp "$i.eps" "$line.eps"
while read line2;
do
mv "$line.eps" "$line2"
sed -i '1d' cate.txt
done < cate.txt
sed -i '1d' cate.txt
((i++))
done < Names.txt
cp "$i.eps" "$line.eps"
Let me explain; I have 2 files totally. One of them is named "Names.txt" which contains the name of files. And the other file is "cate.txt" which contains the name of directories. Also I have .eps files which has name like; 1.eps, 2.eps, etc...
So, what I would like to do is to read the first line in "Names.txt" and than change the first file's name with the first line, and than read first line in "cate.txt" and move the first file under the directory that I read in "cate.txt"
PS 1: I used sed command there because I was always reading the first line in "cate.txt". So, I thought after I read the first line, I can delete it and than read the first line again. But the code was not successful to do that.
PS 2: In this code I can read "Names.txt" and rename .eps files. But when I start reading the "cate.txt" the script doesn't work properly.
Thank you!
Assuming that names.txt and cate.txt have the same number of rows, you can join them together and use that output instead:
#!/bin/bash
i=1
while read filename dirname; do
mkdir -p $dirname
cp $i.file $dirname/$filename
((i++))
done < <(paste names.txt cate.txt)
Example before running:
$ tree
.
|-- 1.file
|-- 2.file
|-- 3.file
|-- cate.txt
`-- dirs.txt
$ cat names.txt
first_file
second_file
third_file
$ cat cate.txt
first_dir
second_dir
third_dir
And after:
$ tree
.
|-- 1.file
|-- 2.file
|-- 3.file
|-- cate.txt
|-- dirs.txt
|-- first_dir
| `-- first_file
|-- second_dir
| `-- second_file
`-- third_dir
`-- third_file
I am getting this error
nameAndMove: line 8: syntax error near unexpected token <'
nameAndMove: line 8:done < <(paste iconNames.rtf iconCate.rtf)'
I googled it and people say that process substitution is not allowed in my terminal. I use mac terminal.
Thank you
Related
I have an executable program that have input and output likes
./my_exe -i filename_input -o filename_output
I want to use the program to run all filename in my folder that has structure likes
root
|-folder_A
|-abc.txt
|-folder_B
|cdf.txt
So, we can use for to do it. But the problem is that I want to automatically make the filename_output from the filename_input by adding the extension '_processed' before '.txt' likes abc.txt is input file name
. Then the output will be abc_processed.txt
How to do it in shell script? This is my current for code
for sub_folder in "${root_folder[#]}"
do
filename_input=$sub_folder/*.txt
filename_output= filename_input/*.txt/processed.txt
echo filename_output
done
The output of my script is root/folder_A/*processed.txt. I do not know why abc is lost
The right solution depends on what you want to do with it.
You should loop over the files you want to rename, not the directories.
for f in */*/*txt; do
echo "With path ${f} ==> ${f//.txt/processed.txt}"
base_f=${f##*/}
echo "Basenames: ${base_f} ==> ${base_f//.txt/processed.txt}"
done
You might want to use find ... | xargs for this when you want to call my_exe with these files.
Make sure your *processed.txt are not converted again!
$ tree root
root
|-- directory-A
| `-- abc.txt
`-- directory-B
`-- def.txt
2 directories, 2 files
$ find root -type f -exec sh -c 'echo ${1%.txt}_processed.txt' _ {} \;
root/directory-B/def_processed.txt
root/directory-A/abc_processed.txt
or:
$ for dir in root/*; do ( cd $dir; for file in *.txt;
do echo "$file --> ${file%.txt}_processed.txt"; done ) done
abc.txt --> abc_processed.txt
def.txt --> def_processed.txt
I am writing a short script. One functionality is synchronizing two folders. Now I have two variables with directories to two different folder: DIRECTORY_1 and DIRECTORY_2. In both folders are files and other folders. I need to synchronize these folder to have all files in both folders. For example:
In DIRECTORY_1 I have file1, file2, file3 and folder1
In DIRECTORY_2 I have file4, file5, file6 and folder2
I need comment after which I will have in both directories files1-6 and folders1-2.
I was trying rsync command but it doesn't work properly.
$ mkdir dir1
$ mkdir dir2
$ touch dir1/file1 dir1/file2 dir1/file3
$ mkdir dir1/folder1
$ touch dir2/file4 dir2/file5 dir2/file6
$ mkdir dir2/folder2
$ tree
.
|-- dir1
| |-- file1
| |-- file2
| |-- file3
| `-- folder1
`-- dir2
|-- file4
|-- file5
|-- file6
`-- folder2
$ rsync -a dir1/ dir2
$ tree
.
|-- dir1
| |-- file1
| |-- file2
| |-- file3
| `-- folder1
`-- dir2
|-- file1
|-- file2
|-- file3
|-- file4
|-- file5
|-- file6
|-- folder1
`-- folder2
I guess rsync -d dir2/ dir1 would be next?
Use unison, it's a real folder synchroniser (such as Dropbox or Mega did).
https://www.cis.upenn.edu/~bcpierce/unison/
Mac installation with brew:
brew install unison
I used this command:
unison -auto /path/folder1 /path/folder2
Moreover, and most important to me, if 2 files have the same name, it replaces with the most recent version.
Likely not the most efficient, but this would do the trick:
comm <(ls DIR1) <(ls DIR2) -23 | while read f; do cp -r DIR2/$f DIR1; done
comm <(ls DIR1) <(ls DIR2) -13 | while read f; do cp -r DIR1/$f DIR2; done
Hi all i am trying to print all the files present in a file here for instance a folder name "WebstormProjects" when i am trying to print the files it is going only upto 2nd sub directory(as written there) only if i want to go much deep into the sub-directory(2nd level) how to go deep down recursively??
here is the tree
WebstormProjects/
|-- goutham
| |-- goutham.js
| |-- demo.html
| |-- format.js
| `-- login.html
`-- Nodejs
|-- prototype
|`-- app.js
`-- requests
`-- app.js
4 directories, 6 files
here is the code
enter code here
#!/bin/bash
target="/home/goutham/WebstormProjects"
for f in "$target"/*
do
if [[ -d $f ]]; then
for k in "$f"/*
do
echo "$k"
done
echo ""
else
echo $f
fi
done
echo ""
Use find:
find WebstormProjects
If you want only files and no directories:
find WebstormProjects -type f
You want the output as list. Use
find WebstormProjects
Or if you want in a tree like you post
tree -af
so I have problem with kinda easy thing:
I have thousands of files which have the same basename, but different extensions(multiple of them). For example I have following:
t_2dri.manual.ali_porter.inseq
t_2dri.manual.ali_porter.inseq.porter
t_2dri.tm.ali_porter.inseq
t_2dri.tm.ali_porter.inseq.porter
t_3ezm.manual.ali_porter.inseq
t_3ezm.manual.ali_porter.inseq.porter
t_8gep.fast.ali_porter.inseq
t_8gep.fast.ali_porter.inseq.porter
what I'd like to get are directiories:
t_2dri.manual.ali
t_2dri.tm.ali
t_3ezm.manual.ali
t_8gep.fast.ali
and I do this with the following script:
for i in *.porter;do
bn=$(basename $i _porter.inseq.porter)
mkdir $bn;done
which works(maybe I can do it better/shorter) ?
the second question is HOW to put the files into correct folders - I tried few scripts and for loops, but no succes yet.
OK, so I got half of the answer I need,but some of them are truly mistifing, now to make it easier for us (me :) ) to understand:
I do have folders named
folder1.sth
folder2.sth
folder3.sth
and in the same directory I do have files like:
folder1.sth.sth.blah
folder3.sth.other.thing
folder1.sth.any.other.thing
how to put every file which is .sth. into corresponding *.sth folder (with the same prefixes)
ok, SUNDAY AFTER DINNER IS THE COSMIC TIME OF THE WEEK
what worked for me (although I can SWEAR it didn't half an hour ago) is:
for i in *.sth;do
mv $i.* $i;
done
ok, so what I was doing wrong is that
for i in *.ali;do
2 mv $i_* $i;
3 done
is not the same as
for i in *.ali;do
2 mv $i.* $i;
3 done
in the way that $i.* is something that was $i it has . later and something after, while $i_ means completly different thing - don't know what yet and how to omit it, maybe somebody will help ?
for base in t_2dri.manual.ali t_2dri.tm.ali t_3ezm.manual.ali t_8gep.fast.ali; do
mkdir $base
mv "${base}*" $base/
done
If you are getting argument list too long errors because there are zillions of files, you just have to loop over them, thusly:
for base in t_2dri.manual.ali t_2dri.tm.ali t_3ezm.manual.ali t_8gep.fast.ali; do
mkdir $base
for file in ${base}*; do
mv "$file" $base/
done
done
I answered a very similar question here Move a group of files to a new folder if their file names, minus extension, matches? A slight change below should work for what you want.
To get the filename in this case, you can use this in bash
"${i%%.ali*}.ali" #This will match the longest possible match of ".ali*" in the string and remove it, leaving everything before it, and then we append ".ali" back to the end.
So modifying the script from the other answer to what you want:
#!/bin/bash
dir="/somedir/"
for i in "$dir"*; do
if [[ -f $i && $i == *".ali"* ]]; then
filename="${i%%.ali*}.ali"
if [ ! -d "$filename" ]; then
mkdir "$filename"
fi
mv "$i" "$filename"
fi
done
For an explanation. Put the dir you want this done on in dir="/somedir/". This will then loop over all files (regular files, directories, symlinks, etc...) in that directory. It then checks if the given file is a regular file containing ali. If it is, it checks if a directory with the given filename up to .ali exists, if it doesn't it makes it, then it moves the file to the relevant directory.
If /somedir/ has the files you list, that produces
|-- t_2dri.manual.ali
| |-- t_2dri.manual.ali_porter.inseq
| `-- t_2dri.manual.ali_porter.inseq.porter
|-- t_2dri.tm.ali
| |-- t_2dri.tm.ali_porter.inseq
| `-- t_2dri.tm.ali_porter.inseq.porter
|-- t_3ezm.manual.ali
| |-- t_3ezm.manual.ali_porter.inseq
| `-- t_3ezm.manual.ali_porter.inseq.porter
`-- t_8gep.fast.ali
|-- t_8gep.fast.ali_porter.inseq
`-- t_8gep.fast.ali_porter.inseq.porter
Update solution for edited question
#!/bin/bash
for i in *".sth"*; do
[ -f "$i" ] && mv "$i" "${i%%.sth*}.sth/"
done
cat INPUT.txt | while read FILE ; do
## skip blank lines & non-existing files in INPUT.txt
if [[ $FILE == "" ]] | [[ ! -f $FILE ]] ; then
continue
fi
## set $BN as dir name
BN=$(basename $FILE| sed 's/\(.*\)_porter.*/\1/')
## make dir if dir does not exist
if [[ ! -d $BN ]] ; then
mkdir $BN
fi
## move file to inside dir
mv $FILE $BN
done
Assumptions:
INPUT.txt is the input file & it contains full paths to existing files
(if file is not found, then operation is skipped)
Unless you change something in the $BN variable, directories will be created in the current working directory (i.e. where you run the script)
I am trying to write a script (preferably in bash) to flatten a java projet directory structure prepending the path to the file. Example:
| src
| org
| apache
| file2.java
| file1.java
would result in:
| src
| org|apache|file2.java
| org|file1.java
The script should be recursive since the directory could have many subfolders.
cd src
for i in $(find . - name '*.java') ; do
echo cp \"$i\" $(echo "$i" | tr / _)
done
if it looks good(might barf if filenames contains spaces), pipe the result to sh