I'm trying to organize a bit my music folder. Right now it has many subfolders inside.
Inside every one of those subfolders, there is a subsubfolder with the artist_name which contains music files.
E.g.:
Music_folder/silly_name001/artist_A;
Music_folder/silly_name002/artist_B_discA;
Music_folder/silly_name003/artist_B_discB;
I can list the content of the Music_ folder and get the names of the subfolders with this:
for i in $(ls -d */); do echo ${i%%/}; done
But when I try to move the content of those subsubfolders to the parent folder, I can't achieve my goal. I'm using this code:
for i in $(ls -d */); do mv ${i%%/*} .; done
Actually, it moves the subsubfolders but not the content of them.
Any ideas about how to achieve it?
Thanks in advance
${i%%/*} removes the longest prefix matching /*; see:
$ i=Music_folder/silly_name003/artist_B_discB;
$ echo ${i%%/*}
Music_folder
You're looking for something like this:
set ./*/
echo mv ./*/* .
echo rmdir "$#"
Drop echos if you're happy with the output.
Note that this can't deal with name collisions.
Related
I am a total newbie and can’t pass a problem.
I have a process that transcode movie files to a folder. The files have a file name with two different prefixes.
I want to make all incoming NT_*.mp4 to be moved to one other predefined folder and all ET_*.mp4 to another predefined folder. They predefined with path and name.
Tried a simple if $fname=NT_*.mp4 then mv file to folder1 elif $fname=ET_*.mp4 mv that file to folder2. And that doesn’t work, it just move all files in the folder to folder1, so that is obviously wrong way.
So what do I need to do for checking each file for it prefix and then move them based on the prefix to predefined folders?
Spaces are important. It looks like you used something like
fname="wrong"
if [[ $fname=="right" ]]; then
echo "Equal"
fi
You should add spaces around the equal sign:
fname="wrong"
if [[ $fname == "right" ]]; then
echo "Equal"
fi
I have video files with this structure : GX**#### where #### is the number of the video.
But sometimes videos are splitted in 2 or 3 files, for instance : GX01#### and GX02####
My problem is that to organise my folders I prefer rename them like this : GX####-1 and GX####-2.
So i ask you the question if I can create a script/command to rename automatically my files to do this ? I can use .bat windows files or .sh linux files. My main problem is that i don't know a command to rename files simply (i saw many solutions which rewrite the entire file). May be if you know just this I will can do my script.
Thanks you in advance.
You can loop through the files and use PE parameter expansion to slice and jumble the strings and mv to rename the files.
Here is an example, first let us create an empty files using touch, but first we need to create a new directory (folder as you call it) and go into that newly created directory, using mkdir and cd.
mkdir newdirectory && cd newdirectory
Now create the empty files using touch.
touch GX01#### GX02#### GX03#### GX04####
Now check the empty files using ls
ls *
The output should be like
GX01#### GX02#### GX03#### GX04####
Now that we have created empty files, we can now do the renaming part.
for file in GX*; do
file1="${file#*??}"
file2=${file1#*??}
file3=${file1%*$file2}
echo mv -v "$file" "${file%*$file1}${file2}"-"$file3"
done
The output should be on stdout (which is your screen) because of the echo.
mv -v GX01#### GX####-01
mv -v GX02#### GX####-02
mv -v GX03#### GX####-03
mv -v GX04#### GX####-04
If you're satisfied with what you see then remove the echo, so mv can actually rename the files. To show how the slicing is done here is an example.
file=GX01####
file1="${file#*??}"
file2=${file1#*??}
file3="${file1%*$file2}"
printf '%s\n' "$file1" "$file2" "$file3"
The output should be something like.
01####
####
01
The ? means a single string from the shell.
A word of caution and advice, make a backup of the files you want to edit just in case the shell made a mistake while you're renaming the files. :-)
Also you should probably use shell globing like nullglob see
http://mywiki.wooledge.org/glob#nullglob
See man bash and look for Parameter Expansion.
PAGER='less +/^[[:space:]]*parameter\ expansion' man bash
Some online resources, with detailed explanation and examples.
http://mywiki.wooledge.org/BashFAQ/073
https://wiki.bash-hackers.org/syntax/pe
You could echo the original and new file names:
for f in GX*; do
echo "$f" $(sed 's/^GX\(..\)\(.*\)/GX\2-\1/' <<< "$f")
done
which should output:
GX01#### GX####-01
GX02#### GX####-02
then use mv -n instead of echo to rename the files.
I have a cloned git repo that I'm working with. In each folder is a file called config.js. I have a script that SHOULD convert each file in the repo, ending in .js, to a csv and rename it to foldername.config.js.csv. What Bash loop should I use to accomplish this? Forgive me, for I don't really know Bash at all, but from what I was able to figure out I did:
for NAME in `find . -iname 'config.js'`; do
DIRNAME=`echo $NAME | cut -d \/ -f 3`
./do_conversion_script.sh $NAME
mv config.js.csv $DIRNAME.config.js.csv
done
This successfully applied the script to all the files but it only converted the file and added .csv to the end of it. So instead of giving me foldername.config.js.csv, it just gave me config.js.csv. Any help is appreciated. Thank you.
At first let me make some assumptions:
Your directory tree looks like:
./dir/a/config.js
./dir/b/config.js
etc.
The do_conversion_script.sh creates the config.js.csv file in the
same directory as config.js.
You want to prepend a suffix to the config.js.csv file with
its parent name as a or b in case of the example above.
The renamed file is located in the same directory as before.
The parent names do not duplicate.
The pathnames do not include any of whitespace, tab and newline.
Then how about:
for name in $(find . -iname 'config.js'); do
dir="${name%/*}"
prefix="${dir##*/}"
./do_conversion_script.sh "$name"
mv -- "$dir/config.js.csv" "$dir/$prefix.config.js.csv"
done
You may need to use two variables which holds the full directory name from the current directory and the one which holds just the parent name.
Hope this helps.
Your way of calculating DIRNAME does not make sense. Say if I have
NAME=a/b/c
echo $NAME | cut -d \/ -f 3
this produces c, not a/b.
You could use
DIRNAME=$(dirname $NAME)
or
DIRNAME=${NAME%/*}
instead. The former is better readable, the latter saves ones child process.
So after exporting a video to a image sequence, I have ended up with way more images than I needed. I would like to trim this down. The images are named 1.png, up to 959.png. Is there a convenient way of doing this with a bash/zsh script? Something like removing every other image and renaming the next to keep the order?
Thanks in advance.
Alright so I found somewhat of a solution.
#!/bin/zsh
c=0
cc=0
ext=".png"
for file in `ls | sort -V`
do
let c=c+1;
let cc=cc+1;
if [ $c -eq 2 ]; then
rm -f $file
c=0
else
let cc=cc-1;
new="$cc$ext"
mv $file $new
fi
done
This will list out all the files in the current directory and loop through them, deleting every other and renaming the next. Just be aware that this will rename the script file too, so you might want to create some logic to avoid that.
I'm making a shell script that I need to make a loop. I have a directory called Files. Inside Files there are two folders. Each holding 500 files (folder1 and folder2). I need to get the filenames from both folder1 and folder2 because I need to concatenate the filename in folder1 with folder2. It needs to do this for every single file in there. So 250,000 times.
Anyone know how I would write that loop so that I can get all the names from both directories and loop correctly?
Assuming you're in bash, then something like this
cd Files
for f1 in folder1/*
do
for f2 in folder2/*
do
concat_name="${f1#*/}-${f2#*/}"
done
done
something like this should do, assuming that the two subdirectories are called dir1 and dir2, this example only echoes the names naturally..
#!/bin/bash
for d1 in `ls Files/dir1`;
do
for d2 in `ls Files/dir2`;
do
echo ${d1}_${d2}
done
done