Id like to add a character a variable.
I have a file path y/photos/family/kids.jpg.
Its currently assigned to a variable $kidsReal
Id like it to be Y:/photos/family/kids.jpg
(It needs to recognize the photos are coming from the Y drive (Y:)
So far I have (??? is where I am stuck):
#!/bin/bash
#find the kids.jpg back one directory and into the family directory
kids=$(find .. -type f -path *family*/* -name *kids.jpg)
#convert to absolute path
kidsReal=$(realpath ${kids})
#add : between y and / to complete path
kidsRealMod= ???
At the end of the day this variable just needs to be read as a file path to be inserted into a command that will also be coded into the script.
Thank you and please let me know if there are any other details needed for this simple problem.
With bash and a regex:
kidsReal='y/photos/family/kids.jpg'
[[ "$kidsReal" =~ (.)(.*) ]] && kidsRealMod="${BASH_REMATCH[1]^}:${BASH_REMATCH[2]}"
echo "$kidsRealMod"
^ converts first character in a variable to upper-case.
Output:
Y:/photos/family/kids.jpg
See: The Stack Overflow Regular Expressions FAQ
Also, you can split your string into two parts by using ${str:from:to} and join it again with ':'.
str="Y/photos/family/img.png";
new_str=${str:0:1}:${str:1}
echo $new_str
Output:
Y:/photos/family/img.png
Related
So I am wondering if there is any way to organize a directory on a mac with the terminal. I am a beginner with using the terminal and just seeing if this is possible.
I have a script that will scrape various pages and save certain data to a file (data irrelevant), such as this picture.
directory that needs organizing
I would like to know if I can write something that will read the file names and create directories that correspond. For example, it runs a loop that will read all files with "Year2014", create a folder named "Year2014", then place the files inside.
If you have any other questions, let me know!
The short answer is "Yes", and the longer answer is there are many ways to do it. Since you are using bash (or any POSIX shell), you have parameter expansion with substring removal available to help you trim text from the end of each filename to isolate the "YearXXXX" part of the filename that you can then use to (1) create the directory, and (2) move the file into the newly created directory.
Presuming Filenames Formatted WeekXXYearXXXX.txt
Take for example a simple for loop where the loop variable f will contain each filename in turn. You can isolate the "WeekXX" part of the name by using a parameter expansion that trims from the right of the string trough 'Y' leaving whatever "WeekXX" is. (save the result in a temporary variable) You can then use that temp variable to remove the "WeekXX" text from the original filename leaving "YearXXXX.txt". You then simply remove ".txt" from the first to arrive at the directory name to put the file in.
Scriptwise it would look like:
for f in *.txt; do ## loop over .txt files using variable $f
tmp="${f%%Y*}" ## remove though 'Y' from right
dname="${f#$tmp}" ## remove contents of tmp from left
dname="${dname%.txt}" ## remove .txt
mkdir -p "$dname" ## create dname (no error if exists)
mv "$f" "$dname" ## move $f to $dname
done
Where the temporary variable used is tmp and the final directory name is stored in the variable dname.
(note: you may want to use mv -i if you want mv to prompt before overwriting if the filename already exists in the target directory)
You can refer to man bash under the Parameter Expansion heading to read the specifics of each expansion which (among many more) are described as:
${var#pattern} Strip shortest match of pattern from front of $var
${var##pattern} Strip longest match of pattern from front of $var
${var%pattern} Strip shortest match of pattern from back of $var
${var%%pattern} Strip longest match of pattern from back of $var
Note this set of parameter expansions is POSIX so it will work with any POSIX shell, while most of the remaining expansions are bashisms (bash-only)
Let me know if you have further questions.
I have a directory with a single file. The name of the file is randomized, but the extension is fixed.
myDirectory
|----file12321.txt
Is there a one-line way to extract the full path of that file?
MY_FILE=myDirectory/*.txt
Current output:
/home/me/myDirectory/*.txt
Expected:
/home/me/myDirectory/file12321.txt
Use readlink to get canonized path.
MY_FILE=$(readlink -f myDirectory/*.txt)
If you want only myDirectory/file12321.txt part you could run a command that will let shell expand *, like:
MY_FILE=$(printf "%s\n" myDirectory/*.txt)
If it's certain that there is exactly one file, you can just use an array:
MY_FILE=( /home/me/myDirectory/*.txt )
Filename expansion takes place inside an array definition but not when setting the value of a normal variable. And you can just use the array like a normal variable, as that will provide the value of the first element:
$ foo=(1 2 3)
$ echo "$foo"
1
MY_FILE=$(pwd)/$(ls myDirectory/*.txt)
# $MYFILE == /home/me/myDirectory/file12321.txt
I'm trying to get the path to the nearest parent directory named foo:
/this/is/the/path/to/foo/bar/baz
yields
/this/is/the/path/to/foo
Any idea how I do this?
Using BASH string manipulation:
p='/this/is/the/path/to/foo/bar/baz'
name='foo'
r="${p%/$name/*}/$name"
echo "$r"
/this/is/the/path/to/foo
OR better would be to use:
p='/this/is/afoo/food/path/to/foo/bar/baz'
echo "${p/\/$name\/*/\/$name}"
/this/is/afoo/food/path/to/foo
BASH FAQ Reference
Try this: This operation (using % sign) will remove anything after foo word (if it's in a variable var from the right side) then suffix it with foo.
echo ${var%/foo/*}foo
or
echo ${var/\/foo\/*/\/foo}
Removing foo (at last) from the above command will give the parent folder of first occurrence of foo folder. Including foo will give you the first foo folder as the parent.
PS: If there's no "/foo/" folder in the path, then, the above echo command will output whatever is the value of given path (i.e. $var as it's) aka it'll output a wrong output for your purpose OR it may work correctly only in case the given path i.e. $var is /foo).
I have a set of files I want to perform an action on in a folder that i'm hoping to write a scipt for. Each file starts with mazeFilex where x can vary from any number , is there a quick and easy way to perform an action on each file? e.g. I will be doing
cat mazeFile0.txt | ./maze_ppm 5 | convert - maze0.jpg
how can I select each file knowing the file will always start with mazeFile?
for fname in mazeFile*
do
base=${fname%.txt}
base=${base#mazeFile}
./maze_ppm 5 <"$fname" | convert - "maze${base}.jpg"
done
Notes
for fname in mazeFile*; do
This codes starts the loop. Written this way, it is safe for all filenames, whether they have spaces, tabs or whatever in their names.
base=${fname%.txt}; base=${base#mazeFile}
This removes the mazeFile prefix and .txt suffix to just leave the base name that we will use for the output file.
./maze_ppm 5 <"$fname" | convert - "maze${base}.jpg"
The output filename is constructed using base. Note also that cat was unnecessary and has been removed here.
for i in mazeFile*.txt ; do ./maze_ppm 5 <$i | convert - `basename maze${i:8} .txt`.jpg ; done
You can use a for loop to run through all the filenames.
#!/bin/bash
for fn in mazeFile*; do
echo "the next file is $fn"
# do something with file $fn
done
See answer here as well: Bash foreach loop
I see you want a backreference to the number in the mazeFile. Thus I recommend John1024's answer.
Edit: removes the unnecessary ls command, per #guido 's comment.
I have a lot of files (images) like this (file names consist only from numbers):
123456.jpg
369258.jpg
987123.jpg
...
I need to make a copy of each in some other folder (let's name it output) and rename each of the file based on numbers in their name, something like this (in pseudocode):
outputFileName = String(filename[0]) + String(filename[1]) + String(filename[2]+filename[3]) + ".jpg"
So as you can see, the renaming involves getting a certain symbol in file name and sometimes getting a sum of some symbols in file name.
I need to make a script to mass rename all *.jpg in the folder where I put the script based on similar algorithm, and output renamed ones in output folder I mentioned earlier.
This script should be workable from macos terminal and windows via cygwin shell.
I assume main problems are: how to get particular character of bash variable and how to perform addition in bash.
To obtain a char from bash variable you can use this form: ${var:START_INDEX:LENGTH}.
To perform addition: $((ARG1 + ARG2))
Your resulting script may be like that:
#!/bin/bash
for f in *.jpg
do
output=${f:0:1}${f:1:1}$((${f:2:1} + ${f:3:1})).jpg
mv -- "$f" "$output"
done
You are looking for substring extraction.
The syntax is ${string:position:length}, where string is the name of the variable, position is the starting position (0 is the first index), and length is the length of the substring.
A script that would create the filenames as specified in the question, and copy them for a folder named "input" to a folder named "output" could look like this:
#!/bin/bash
for file in input/*.jpg
do
filename="$(basename "$file")"
firstChar="${filename:0:1}"
secondChar="${filename:1:1}"
thirdAndFourthChar="$(( ${filename:2:1} + ${filename:3:1} ))"
newfilename="$firstChar$secondChar$thirdAndFourthChar.jpg"
cp "$file" "output/$newfilename"
done