Changing the file names and copying into different directory - linux

I have some files say about 1000 numbers.. Wanted to rename those files in such a way that, wanted to cut out only few chars from file name and copy it to some other directory.
Ex: Original file name.
vfcon062562~19.xml
vfcon058794~29.xml
vfcon072009~3.xml
vfcon071992~10.xml
vfcon071986~2.xml
vfcon071339~4.xml
vfcon069979~43.xml
Required O/P is cutting the ~and following chars.
O/P Ex:
vfcon058794.xml
vfcon062562.xml
vfcon069979.xml
vfcon071339.xml
vfcon071986.xml
vfcon071992.xml
vfcon072009.xml
But want to place n different directory.

If you are using bash or similar you can use the following simple loop:
for input in vfcon*xml
do
mv $input targetDir/$(echo $input | awk -F~ '{print $1".xml"}')
done
Or in a single line:
for input in vfcon*xml; do mv $input targetDir/$(echo $input | awk -F~ '{print $1".xml"}'); done
This uses awk to separate everything before ~ using it as a field separator and printing the first column and appending ".xml" to create the output file name. All this is prepended with the targetDir which can be a full path.
If you are using csh / tcsh then the syntax of the loop will be slightly different but the commands will be the same.

I like to make sure that my data set is correct prior to changing anything so I would put that into a variable first and then check over it.
files=$(ls vfcon*xml)
echo $files | less
Then, like #Stefan said, use a loop:
for i in $files
do
mv "$i" "$( echo "$file" | sed 's/~[0-9].//g')"
done
If you need help with bash you can use http://www.shellcheck.net/

Related

Problem with splitting files based on numeric suffix

I have a file called files.txt and I need to split it based on lines. The command is as follows -
split -l 1 files.txt file --numeric-suffixes=1 --suffix-length=4
The numeric suffixes here start from file0001 to file9000. But I want it to be from 1 to 9000.
I can't seem to change it when --suffix-length=1, as split exhausted output filenames. Any suggestions using the same split command?
I don't think split will do what you want it to do, though I'm on macOS, so the *nix I'm using is Darwin not Linux; however, a simple shell script would do the trick:
#!/bin/bash
N=1
cat $1 | while read line
do
echo "$line" > file$N
N=`expr $N + 1`
done
Assuming you save it as mysplit (don't forget chmod -x mysplit), then you run it:
./mysplit files.txt

How do I loop over multiple files to extract specific columns and save as separate files?

I have numerous *.txt files. I want to extract column 3 and 5 from each of these files and save them as new files keeping their oiginal names with new_ extension. I have this bash loop below in trying to do this, but doesn't do what I want. Can someone please help me with this?
for i in *.txt; do
cut -f 3,5 $i > /media/owner/new_$i_assembly.txt
done
Simple approach:
for f in *.txt; do
cut -d$'\t' -f3,5 "$f" > "/media/owner/new_${f}_assembly.txt"
done
In case if there could be possible whitespace(s) except tabs - you may use the following awk approach:
for f in *.txt; do
awk '{ print $3,$5 }' OFS='\t' "$f" > "/media/owner/new_${f}_assembly.txt"
done
You have to make sure and tell Bash explicitly to expand variable $i, otherwise it picks up characters you don't want and expands variable $i_assembly instead:
for i in *.txt; do
cut -f 3,5 "$i" > "/media/owner/new_${i}_assembly.txt"
done
If you don't want the extension included in your new name, use parameter expansion ${i%.*} that removes everything up to the first . included, from the end.
for i in *.txt; do
cut -f 3,5 "$i" > "/media/owner/new_${i%.*}_assembly.txt"
done
If you decide for a different approach that might result in paths, not just filenames (for example: **/*.txt), you can use parameter expansion once again to get only the name of your file:
for i in **/*.txt; do
base=${i##*/}
base=${base%.*}
cut -f 3,5 "$i" > "/media/owner/new_${base}_assembly.txt"
done
Also note that TAB is the default delimiter for cut, you don't need to specify it with the -d option:
-d, --delimiter=DELIM
use DELIM instead of TAB for field delimiter

Rename file while keeping the extension in Linux?

I have a directory that contains multiple files with different extensions (pdf, doc, txt...etc).
I'm trying to rename all files according to the directory name while keeping the file extension the same. The code below works fine if all files are PDF otherwise it will change txt file extension to pdf too.
How can I rename files while preserving the file extension
mv "$file" "${dir}/${dir}-${count}.pdf"
I assume you're doing this in some kind of loop? If so, you could grab the file extension first with
ext="${file##*.}" # eg. ext="txt", ext="pdf"...
And replace pdf with $ext in your mv command. Tested with sh, bash, dash, ksh.
you can do this through bash.
can you please provide more details. how your deciding this $dir and $count variable value.
if you already know by what you want to change the file name like below
OLD NAME|NEW NAME|Path
test.1|newtest.1|Path
arty.2|xyz.2|Path
if you want to replace it by specific names then you can prepare a list like above and then traverse through the file by while or for loop. below is simple bash snippet for case where you have files under multiple directory
while IFS="|" read OLD NEW PATH
do
cd $Path
filename=`echo $NEW|awk -F '.' '{print $1}'`
filetype=`echo $NEW|awk -F '.' '{print $2}'`
mv $OLD $filename.$filetype
done<FILE_PATH
if want to perform operation under single directory then below snippet will work.
for i in $(ls /tmp/temp)
do
filename=`echo $i|awk -F "." '{print $1}'`
fileType=`echo $i|awk -F "." '{print $2}'`
mv $i $filename.$fileType
done

Copying Multiple files using cp

I want to copy multiple files in one go using cp. The problem is that the filenames contain spaces here and there. So I tried cp $(ls -1|tr ' ' '') dest but apparently I cannot truncate to nothing. Then I tried removing null space to spaces. That didnt work either. I tried running it over a for loop. That too didnt work. Can some one please help me????
You might want to try using find in combination with xargs and cp. See How can I use xargs to copy files that have spaces and quotes in their names? for more info.
Ahn, ok.
I was writing this:
for i in *
do
if echo $i | grep " "
then
NEWNAME=`echo $i | tr ' ' '_'`
mv "$i" $NEWNAME
fi
done
But in this case you rename the file (and of course you have to adapt the code to your needs)
I have this function in my .bashrc
The problem is that you can't tr the source file names for cp - you have to give it the names of the files as they exist on disk or it won't find them. So it sounds like what you effectively want is to cp "file with spaces" destdir/filewithspaces for each individual file:
ls -1 | while read filename; do
cp "$filename" "$dest/${filename// /}"
done
The ${filename// /} is an instance of the bash-ism ${variable//search/replacement} (see shell parameter expansion in the Bash manual) to give the value of a variable with all instances of the search string replaced with the replacement string - so in this case replace all spaces with nothing.

passing awk variable to bash script

I am writing a bash/awk script to process hundreds of files under one directory. They all have name suffix of "localprefs". The purpose is to extract two values from each file (they are quoted by ""). I also want to use the same file name, but without the name suffix.
Here is what I did so far:
#!/bin/bash
for file in * # Traverse all the files in current directory.
read -r name < <(awk ' $name=substr(FILENAME,1,length(FILENAME)-10a) END {print name}' $file) #get the file name without suffix and pass to bash. PROBLEM TO SOLVE!
echo $name # verify if passing works.
do
awk 'BEGIN { FS = "\""} {print $2}' $file #this one works fine to extract two values I want.
done
exit 0
I could use
awk '{print substr(FILENAME,1,length(FILENAME)-10)}' to extract the file name without suffix, but I am stuck on how to pass that to bash as a variable which I will use as output file name (I read through all the posts on this subject here, but maybe I am dumb none of them works for me).
If anyone can shed a light on this, especially the line starts with "read", you are really appreciated.
Many thanks.
Try this one:
#!/bin/bash
dir="/path/to/directory"
for file in "$dir"/*localprefs; do
name=${file%localprefs} ## Or if it has a .: name=${file%.localprefs}
name=${name##*/} ## To exclude the dir part.
echo "$name"
awk 'BEGIN { FS = "\""} {print $2}' "$file" ## I think you could also use cut: cut -f 2 -d '"' "$file"
done
exit 0
To just take sbase name, you don't even need awk:
for file in * ; do
name="${file%.*}"
etc
done

Resources